How to Use an AI Agent to Capture a Webpage Screenshot with Browser Geolocation
Set a controlled browser location, wait for the page to update, and capture a reproducible screenshot with Playwright or an AI agent.
To capture a location-specific webpage screenshot with an AI agent, configure the browser context with the latitude and longitude, grant the geolocation permission, open the page, wait for its location-dependent content to update, and then save a screenshot. The runnable Playwright example below follows that sequence. It emulates what the browser reports; it does not prove that a real person or device is physically at those coordinates.
This guide uses Playwright, which exposes geolocation and permission controls at the browser-context level. That makes it a practical fit for an agent or test script that needs a repeatable browser session. For reproducible results, also choose the browser engine, viewport, locale, timezone, cookies, and account state deliberately: a website may use those inputs, its own location rules, or IP-based location in addition to browser geolocation.
1. Set up a Playwright browser with a chosen location
Install Playwright and its Chromium browser in a Node.js project:
npm install --save-dev playwright
npx playwright install chromium
Save this as capture-location.js. Replace the target URL with a page you are authorized to inspect. The coordinates are Playwright’s documented example values, not a claim of testing at that location.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
try {
const context = await browser.newContext({
geolocation: { latitude: 41.890221, longitude: 12.492348 },
permissions: ['geolocation'],
viewport: { width: 1440, height: 1000 },
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
// Replace this with a condition specific to the application under test.
// For example: await page.locator('[data-testid="location-result"]').waitFor();
await page.screenshot({ path: 'location-view.png', fullPage: true });
await context.close();
} finally {
await browser.close();
}
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Run it with node capture-location.js. The example uses domcontentloaded as a navigation milestone, but that alone does not mean a location lookup or application update has finished. Replace the comment with a wait for the actual result, such as a location label or a known element that appears after the site processes the browser location. Playwright’s emulation guide documents geolocation and context permissions; its Page API documents screenshot capture.
What the context settings do
geolocationsets the coordinates exposed to pages in the context.permissions: ['geolocation']grants the browser permission required for a page to access that location without depending on a manual prompt.viewportfixes the visible browser area so the screenshot has a predictable viewport size. Choose dimensions that match the layout you want to inspect.fullPage: truecaptures the full scrollable page. Omit it when the viewport alone is the intended evidence.
Set location and permission before opening the page or triggering its location flow. The browser context is the scope: pages opened in that context share its settings.
2. Wait for the location-dependent state
A successful navigation is not proof that the page used the mocked coordinates. The page must request browser geolocation, receive it, and update its interface or data. Prefer a condition that represents the result you need over a fixed delay:
// Wait for a result element that your application displays after its location lookup.
await page.locator('[data-testid="location-result"]').waitFor({ state: 'visible' });
await page.screenshot({ path: 'location-view.png', fullPage: true });
The selector above is an example; use a selector from the target application. If the page exposes no stable result element, a short delay can be a fallback, but it is less reliable because network and rendering times vary. Do not capture while the page still shows a loading state if the purpose is to document the resolved location.
If the agent needs to test a second location in the same context, change the coordinates and wait for the application to react before taking the next screenshot:
await context.setGeolocation({ latitude: 40.7128, longitude: -74.0060 });
// Wait for the app's location-dependent result to update before capture.
await page.locator('[data-testid="location-result"]').waitFor({ state: 'visible' });
await page.screenshot({ path: 'second-location.png', fullPage: true });
When the same selector remains visible across updates, visibility alone may not prove that new content arrived. Wait for the displayed value to change, or for an application-specific loading indicator to complete. Playwright documents context.setGeolocation(...) for changing the context location; the change applies to its pages.
3. Configure repeatable Playwright tests
For Playwright Test, put the location and permission in the test configuration so each test receives the same browser context defaults. Add this to playwright.config.js:
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
use: {
browserName: 'chromium',
viewport: { width: 1440, height: 1000 },
geolocation: { latitude: 41.890221, longitude: 12.492348 },
permissions: ['geolocation'],
},
});
A test can then navigate, wait for the location result, and capture evidence:
const { test, expect } = require('@playwright/test');
test('renders the location-specific result', async ({ page }) => {
await page.goto('https://example.com');
const result = page.locator('[data-testid="location-result"]');
await expect(result).toBeVisible();
await page.screenshot({ path: 'location-view.png', fullPage: true });
});
Install the test runner if needed with npm install --save-dev @playwright/test. Keep the browser engine, viewport, locale, timezone, and test data explicit when screenshots need to be comparable. Geolocation does not set all of those values, and it does not control a website’s IP-based location logic.
4. Choose screenshot scope and format
| Need | Playwright choice | Consideration |
|---|---|---|
| Show what is visible in the browser | await page.screenshot({ path: 'viewport.png' }) |
Captures the viewport; content below the fold is not included. |
| Show the full scrollable document | await page.screenshot({ path: 'full.png', fullPage: true }) |
Long pages create taller images and may expose lazy-load or sticky-layout behavior that differs while scrolling. |
| Capture a specific element | await page.locator('.map-panel').screenshot({ path: 'map.png' }) |
Useful when the evidence is a location card or map rather than the whole page. |
| Reduce image payload size | await page.screenshot({ path: 'view.jpg', type: 'jpeg', quality: 80 }) |
JPEG is lossy; inspect text and fine interface details before using it as evidence. |
| Keep crisp interface details | await page.screenshot({ path: 'view.png', type: 'png' }) |
PNG is lossless and often suitable for UI evidence. |
Playwright’s screenshot API supports page capture and full-page capture. Chrome’s agent configuration documentation describes PNG, JPEG, and WebP screenshot formats; format support and options depend on the specific tool or API. Name outputs predictably and retain the coordinates and configuration alongside the image if you need to reproduce a result.
5. Use an AI agent safely and reproducibly
An AI agent can write or operate the browser script, but the location remains a test input. Use this workflow for pages and interactions you are authorized to inspect:
- Give the agent the target URL, the chosen coordinates, the expected location-dependent state, and the required screenshot scope.
- Have it set geolocation and grant permission on the context before page interaction.
- Ask it to wait for a page-specific result condition, not just navigation completion.
- Have it save the screenshot with a stable filename and report the coordinates and browser settings used.
- Review the image for loading states, stale content, blocked maps, or a location that appears to come from another source.
Browser geolocation emulation affects what browser APIs report. It does not change the machine’s physical position or establish that a user is actually present there. A site may combine browser location with IP address, cookies, account settings, locale, or its own location-selection logic. Keep those variables in mind when interpreting a screenshot.
For agents already using Chrome DevTools Protocol (CDP), the protocol exposes Page.captureScreenshot, including format and clip options. Its current Page reference marks Page.setGeolocationOverride as deprecated, so use Playwright’s documented geolocation API for a new Playwright workflow. CDP is a lower-level route; check the current protocol reference before building an agent around it. See the CDP Page reference.
6. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. A single GET request captures a URL as PNG, JPEG, WebP, or PDF. Its geolocation option can set a location for the capture; the example below uses the documented API and an example target URL. See the ScreenshotNeo API documentation for the available parameters, including timezone and geolocation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
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);
To request a location, add the geolocation parameter from the API documentation to the query. ScreenshotNeo’s documented product facts include timezone and geolocation controls, but do not specify a parameter spelling here; copy the exact parameter and coordinate format from the docs. The Node.js snippet uses Bun’s file writer; in a Node.js-only runtime, save the response with writeFile from node:fs/promises:
import { writeFile } from 'node:fs/promises';
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 writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo accepts cookie or consent banners before capture and removes 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000, and every feature is on every plan. That can simplify routine URL capture, but a browser context is still the route when you need to control the Playwright session itself.
Sign up for 1,000 free screenshots a month, with no card required.
7. Troubleshooting geolocation screenshots
| Symptom | Likely cause | Fix |
|---|---|---|
| The page asks for permission or reports location unavailable | The context did not grant geolocation permission, or the page was opened in a different context. | Set permissions: ['geolocation'] and geolocation on the context used to create the page, before navigation. |
| The page ignores the mock | The page may not call a browser geolocation API, or its location display may use IP, account, cookie, or manually selected location instead. | Confirm the page’s location mechanism. Treat the screenshot as a browser-geolocation test only when the page consumes that browser value. |
| An embedded map or frame cannot access location | Permissions Policy may restrict feature access for a page, embedded frame, or subresource. | Inspect the page and frame policy and the site’s configuration. Chrome explains how Permissions Policy controls browser features. |
| The screenshot shows a spinner or the previous location | Navigation finished before the location request or UI update. | Wait for a result-specific selector or changed value; avoid relying only on goto completion or an arbitrary short timeout. |
| The output is unexpectedly tall or the lower page is incomplete | Full-page capture includes the scrollable document, and below-the-fold content may load lazily. | Use viewport capture if that is the required evidence, or ensure the content has loaded before full-page capture. |
| The screenshot is hard to compare between runs | Viewport, browser engine, locale, timezone, cookies, account state, or page data may differ. | Pin the relevant context and test settings, and record the coordinates with the image. |
Chrome’s Permissions Policy documentation notes that feature access can be controlled for pages and embedded frames. Browser feature permissions are distinct from a site’s own location logic. Automation frameworks can configure permissions for test contexts, so an automated run does not necessarily display an interactive permission prompt.
8. Performance, reliability, and cost
- Wait on meaningful state. A specific result condition avoids capturing too early and usually makes the run less sensitive to variable network timing than a guessed delay.
- Keep the browser lifecycle bounded. Close the context and browser even when navigation or capture fails; the example uses
try/finallyaround the browser. - Choose the smallest useful capture. A viewport or element screenshot can produce a smaller artifact than a very long full-page capture. JPEG or WebP can reduce payload where supported and where lossy output is acceptable.
- Separate test inputs. Record coordinates, viewport, locale, timezone, browser engine, and relevant account or cookie state so a later run can reproduce the conditions.
- Budget browser resources. A local Playwright workflow uses a browser runtime and the time and compute required to load the target page. Avoid setting a short hard timeout that turns a slow but authorized page into an unexplained missing screenshot; instead report navigation and wait failures clearly.
- Check service billing semantics. ScreenshotNeo bills only clean shots: bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Its response includes
X-Page-VerdictandX-Billedheaders. The Free plan is 1,000 shots monthly with no card; paid tiers range from Starter at $5 for 3,000 to Business at $249 for 1,000,000, and yearly billing gives two months free.
9. FAQ
Does mocked geolocation prove a visitor is in that place?
No. It changes the location reported by the automated browser for testing. It does not verify a person’s or device’s physical location.
Can I change the location without starting another browser?
Yes. Playwright supports context.setGeolocation(...); wait for the site’s state to update before capturing again.
Why is granting permission not enough?
Permission only allows the page to use browser geolocation. The page must request it and use the returned value, and its policy and application logic must permit the feature.
Should I use CDP instead of Playwright?
Use CDP when the agent already operates at the protocol level and needs its screenshot controls. For new Playwright automation, use Playwright’s higher-level geolocation API; CDP’s current geolocation override reference is marked deprecated.


