ScreenshotNeo

BlogHow-to

How to Set Permissions in a Puppeteer BrowserContext

Grant, deny, and reset browser permissions for a specific origin in Puppeteer, with examples, version notes, and fixes for common problems.

By the ScreenshotNeo team4 October 20267 min read

Set permissions on a Puppeteer BrowserContext, scoped to the origin that needs them. In the stable Puppeteer 25.12.0 API, context.overridePermissions(origin, permissions) is documented but deprecated. The current Next API documents context.setPermission(origin, ...permissions), which specifies a state for each permission. Check the reference for your installed Puppeteer version before choosing between them: the cited stable and Next references do not establish that the newer signature is available in every stable release.

A context is the configuration scope; a Page does not provide the permission setter. Set the permission before navigating to or exercising the feature. A new context also isolates its storage from other contexts. See Puppeteer’s BrowserContext API reference.

Grant a permission with the stable API

This runnable example uses the stable, deprecated override API to grant geolocation to https://example.com, set the page’s location, and visit the origin. Install Puppeteer in a Node.js project with npm install puppeteer, then save this as permissions.cjs and run node permissions.cjs.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const context = browser.defaultBrowserContext();

  try {
    await context.overridePermissions('https://example.com', ['geolocation']);

    const page = await context.newPage();
    await page.setGeolocation({ latitude: 37.7749, longitude: -122.4194 });
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

    const position = await page.evaluate(() => new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(
        ({ coords }) => resolve({ latitude: coords.latitude, longitude: coords.longitude }),
        error => reject(new Error(`${error.code}: ${error.message}`)),
      );
    }));

    console.log(position);
  } finally {
    // Removes all permission overrides in this context.
    await context.clearPermissionOverrides();
    await browser.close();
  }
})();

Replace the origin and permission with the values required by the page. An origin includes its scheme and host, and can include a port; it is not a path-specific URL. For example, https://example.com is an origin, while https://example.com/account is a URL with a path. Keep the configured origin aligned with the page’s actual origin, including whether it uses HTTP or HTTPS.

Use the newer explicit-state API when your version supports it

The current Next API documents a descriptor and state object for each permission. For example, grant geolocation and explicitly set notifications to denied:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const context = await browser.createBrowserContext();

  try {
    await context.setPermission(
      'https://example.com',
      { permission: { name: 'geolocation' }, state: 'granted' },
      { permission: { name: 'notifications' }, state: 'denied' },
    );

    const page = await context.newPage();
    await page.setGeolocation({ latitude: 37.7749, longitude: -122.4194 });
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  } finally {
    await context.close();
    await browser.close();
  }
})();

The Next reference accepts an origin string or '*' and a variable number of permission/state objects. Do not assume the wildcard is appropriate for a test that should only affect one site: use the specific origin to keep the permission scope narrow. The cited reference does not say that permissions omitted from setPermission are automatically denied, so do not transfer that behavior from the legacy override API.

Check the installed version’s API reference and typings before using this snippet. The stable 25.12.0 reference marks overridePermissions deprecated in favor of setPermission, but the dossier’s Next reference is future-facing and does not prove availability or identical behavior in every stable release. See the Next BrowserContext reference.

Choose the right context and permission behavior

  • Default context: Use browser.defaultBrowserContext() when the permission setup belongs to the browser’s default context. It cannot be closed independently.
  • Dedicated context: Use await browser.createBrowserContext() for a test that should have its own storage and permission configuration. Close it with await context.close() when finished.
  • Legacy override: overridePermissions(origin, ['geolocation']) grants the listed permissions for that origin; the stable API documentation says permissions omitted from the array are automatically denied. This is a broad override for that origin, so include every permission the test needs.
  • Explicit state: Where supported, setPermission pairs each descriptor with a state such as 'granted' or 'denied'. The cited Next signature accepts permission/state objects. Verify the accepted states and descriptors against your installed version.
  • Reset: clearPermissionOverrides() clears all permission overrides for the context. The documented reset is context-wide, not an origin-specific undo.

For older examples, permission names include geolocation, notifications, camera, microphone, clipboard-read, and clipboard-write. The legacy Permission type reference is marked obsolete, so treat it as historical context, not a complete compatibility list. Browser support and behavior can depend on the permission descriptor and browser version; the researched official references do not provide a full compatibility matrix.

Grant clipboard access

The stable override form can grant clipboard permissions to an origin. The Puppeteer Mouse API documentation discusses granting both read and write access for clipboard operations. Add only the access your test requires:

await context.overridePermissions('https://example.com', [
  'clipboard-read',
  'clipboard-write',
]);

const page = await context.newPage();
await page.goto('https://example.com');

For the newer API, use descriptors and explicit states only if the installed version supports the signature and descriptor names you need. Refer to the stable BrowserContext reference and the Puppeteer page interactions guide.

Common errors and fixes

Symptom Likely cause Fix
The browser still asks for permission, or the API reports permission denied. The override was set on another context, for another origin, or after the page tried to use the feature. Set the permission on the context that owns the page before navigation or feature use. Match the origin’s scheme, hostname, and port.
overridePermissions is marked deprecated. The stable API reference now recommends setPermission. Check whether your installed Puppeteer release supports the newer descriptor/state signature. If it does not, use the documented legacy method while planning a version-aware migration.
A permission name or descriptor is rejected. The installed Puppeteer/browser combination may not recognize that name or descriptor, or the API shape may differ by version. Check the exact installed version’s API reference and TypeScript definitions; try a permission documented for that version and browser.
Another permission unexpectedly becomes denied. The legacy override API denies permissions omitted from its list for that origin. Include every permission the page needs in the override array. With setPermission, specify the states you need and verify omission behavior in the installed version.
A later test behaves differently after cleanup. clearPermissionOverrides() clears all overrides in the context, including overrides another part of the test had set. Use a dedicated context per test when permission configurations differ, or coordinate context-wide setup and cleanup.
Geolocation is allowed but the page receives an error or unexpected coordinates. Permission grants access; it does not itself define the reported location. Set coordinates with page.setGeolocation({ latitude, longitude }) and inspect the error callback and the page’s actual origin.

Reliability, performance, and cleanup

Configure permissions before the page feature runs to avoid timing-dependent results. Keep tests that need different permission states in separate contexts where practical; contexts isolate storage, and their context-wide reset avoids accidentally carrying test overrides forward. Always close a dedicated context and browser in cleanup paths, including when navigation or page code throws.

Permission setup is a small part of browser automation; the main reliability risks are mismatched origins, unsupported permission descriptors, version differences, and cleanup shared across tests. The research dossier establishes no performance benchmarks or cost figures for these APIs. For repeatable automation, pin Puppeteer and its browser installation, and check the documentation for the version actually deployed rather than relying on the future-facing Next API.

Or skip the browser setup

If your goal is to capture a website rather than exercise its permission behavior in a browser test, ScreenshotNeo provides a website screenshot API. Its one-call request returns an image or PDF; see the API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

ScreenshotNeo removes known cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed; responses include page-verdict and billing headers. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

FAQ

Can I set a permission on a Puppeteer Page?

Use the BrowserContext that owns the page. The permission API is context-scoped and configured for an origin.

Does clearing overrides reset just one website?

No. The documented method clears all permission overrides for that browser context.

Does granting geolocation set the location?

No. Grant permission on the context, then set coordinates on the page with page.setGeolocation().

Should I use the Next API in production?

Only after confirming that your installed Puppeteer version supports its signature. The Next documentation can change and does not establish stable-release availability.