How to Monitor a Website Screenshot When the Page Has a Geolocation Prompt
Monitor location-sensitive pages by fixing the browser’s location and permission state, capturing the right area, and comparing stable screenshots.
To monitor a website whose content depends on geolocation, set a fixed location and permission state in browser automation, then capture the page after it reaches the state you want to track. A granted geolocation permission produces a location-aware page; it does not reproduce the browser’s human-facing permission prompt. If the prompt itself is what you need to monitor, validate that separately in the exact browser and version used by your monitor.
This guide uses Playwright to monitor allowed-location content and to save screenshots. It also explains how to approach denied access and prompt-visible checks, how to choose screenshot scope, and how to keep comparisons meaningful across runs.
1. Choose the state you want to monitor
A geolocation prompt and a page rendered after a permission decision are different states. Decide which one should trigger an alert before building the monitor.
| Target state | What to configure | What the screenshot tells you |
|---|---|---|
| Location-specific content | Set fixed coordinates and grant geolocation permission. | Whether the page looks as expected for that location. |
| Permission-denied experience | Set the permission to denied and capture the resulting page. | Whether the site handles denied location access as expected. |
| Browser prompt visible | Use the exact browser and version in which the prompt matters; validate its behavior in that environment. | Whether that browser environment displays the expected prompt. |
Do not treat a granted permission test as a prompt test. The Playwright emulation guide documents setting a location and granting the geolocation permission; it does not establish a universal way to display or control the human-facing prompt. Prompt behavior depends on browser and version. Playwright: Emulation
2. Set up a repeatable Playwright monitor
The following runnable Node.js example creates a fresh browser context with a fixed viewport, coordinates, and granted permission, opens a target URL, waits for a chosen page condition, and saves a full-page screenshot. Install Playwright and its browser first:
npm install playwright
npx playwright install chromium
Save this as monitor.mjs. Set TARGET_URL, and optionally set LATITUDE and LONGITUDE in the environment.
import { chromium } from 'playwright';
const targetUrl = process.env.TARGET_URL ?? 'https://example.com';
const latitude = Number(process.env.LATITUDE ?? '37.7749');
const longitude = Number(process.env.LONGITUDE ?? '-122.4194');
if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) {
throw new Error('LATITUDE and LONGITUDE must be valid numbers');
}
const browser = await chromium.launch({ headless: true });
try {
const context = await browser.newContext({
viewport: { width: 1440, height: 1000 },
geolocation: { latitude, longitude },
permissions: ['geolocation'],
deviceScaleFactor: 1,
});
const page = await context.newPage();
await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 });
// Prefer a meaningful page condition when the site has one.
// Replace this with a selector that signals location-specific content is ready.
await page.waitForTimeout(1500);
await page.screenshot({ path: 'location-allowed.png', fullPage: true });
await context.close();
} finally {
await browser.close();
}
Run it with:
TARGET_URL=https://example.com LATITUDE=37.7749 LONGITUDE=-122.4194 node monitor.mjs
The example uses a short delay only as a placeholder. If the page exposes a reliable readiness selector, wait for it instead, for example await page.locator('[data-location-results]').waitFor(). Playwright supports setting coordinates and changing geolocation later for pages in the same context. Keep the permission state, browser configuration, viewport, and coordinates consistent for comparable runs. Playwright emulation documentation
3. Monitor denied access or a prompt-visible state
Denied permission
To monitor the site’s fallback when a visitor refuses access, create a separate context with geolocation permission denied. Do not reuse the allowed-state screenshot as the baseline for this scenario.
const deniedContext = await browser.newContext({
viewport: { width: 1440, height: 1000 },
permissions: [],
});
await deniedContext.grantPermissions([], { origin: targetUrl });
// For a deterministic denied state, use the browser's permission controls
// for your Playwright version and target origin, then verify the page behavior.
const deniedPage = await deniedContext.newPage();
await deniedPage.goto(targetUrl, { waitUntil: 'domcontentloaded' });
await deniedPage.screenshot({ path: 'location-denied.png', fullPage: true });
await deniedContext.close();
Permission defaults and overrides can vary with browser and Playwright version. Verify that the application actually reaches its denied-location branch before accepting the screenshot. One robust approach is to assert a site-specific fallback selector or message in addition to saving the image.
Prompt visible
A browser permission prompt is browser chrome, not ordinary page content. Playwright’s documented grant-and-coordinate setup represents permission already granted, so it should not be used to claim the prompt is visible. If the prompt is the monitored subject, run the check in the same browser, version, operating environment, and permission-history conditions as the real monitor. Validate that the prompt is actually present; do not assume a page screenshot includes browser chrome. Historical prompt illustrations are not a reliable reference for current interfaces.
4. Choose the screenshot scope
Match the capture to the signal you care about. Playwright supports viewport, element, and full-page screenshots. A viewport capture is usually appropriate when the prompt or key content is visible above the fold; an element capture narrows comparison to a component; a full-page capture includes content below the fold. Playwright: Screenshots
// Current viewport
await page.screenshot({ path: 'viewport.png' });
// One component
await page.locator('[data-location-results]').screenshot({ path: 'results.png' });
// Entire scrollable page
await page.screenshot({ path: 'full-page.png', fullPage: true });
Full-page capture can trigger lazy-loaded content as the page is scrolled or captured. Use it when that below-the-fold content matters, and ensure the page has finished loading it before comparison. For a prompt-visible check, first confirm the browser capture mechanism can include the prompt surface; a normal page screenshot may only capture the webpage.
5. Compare runs without confusing state changes for site changes
For reliable visual monitoring, record the conditions that produced each baseline. At minimum, keep the URL, browser name and version, coordinates, permission state, viewport, device scale factor, capture scope, and relevant wait condition fixed. A change in any of those can produce a different screenshot without a website change.
For automated regression checks, Playwright’s screenshot assertions wait until two consecutive screenshots are stable before comparing the result to an expectation. These assertions are part of the Playwright test runner. Playwright: Visual comparisons
import { test, expect } from '@playwright/test';
test('location results are visually stable', async ({ page, context }) => {
await context.grantPermissions(['geolocation']);
await context.setGeolocation({ latitude: 37.7749, longitude: -122.4194 });
await page.setViewportSize({ width: 1440, height: 1000 });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('[data-location-results]').waitFor();
await expect(page).toHaveScreenshot('location-results.png', { fullPage: true });
});
Configure the Playwright project and browser installation according to the test runner’s documentation. Keep prompt-visible monitoring separate from this granted-permission assertion unless the test environment has been validated to capture the prompt itself.
6. Keep the monitor reliable and efficient
- Wait for meaning, not just time. Prefer an application selector or other readiness condition over a long fixed sleep. Use a bounded timeout so a stalled page fails clearly.
- Keep scenarios separate. Maintain distinct baselines for allowed, denied, and prompt-visible states. Label each image with its coordinates and permission state.
- Control the viewport. Use identical width, height, and device scale factor. Responsive layout changes can look like content changes.
- Watch dynamic regions. Ads, rotating content, timestamps, and animations can create noisy diffs. Wait for a stable state or exclude known dynamic areas from the comparison if your tooling supports it.
- Limit capture scope. A targeted element screenshot is often faster to inspect and less sensitive to unrelated page changes. Use full-page capture only when necessary.
- Handle failures explicitly. Capture navigation errors and timeouts as monitor failures, not as valid baseline images. Retry transient network failures with a limit, and preserve the error details.
Screenshot assertions’ stability wait helps reduce transient visual noise, but it cannot make a nondeterministic page deterministic. The site, network, browser version, and permission state still affect the result.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The page shows a location error despite configured coordinates. | The context did not grant geolocation permission, the site origin differs, or the site queried before setup. | Set coordinates and permission on the context before navigation; check the exact origin and confirm the app’s location result. |
| The screenshot has location-specific content but no permission prompt. | Permission was granted, so the browser has no reason to ask the visitor. | Treat this as the allowed state. Validate a prompt-visible check separately in the actual target browser environment. |
| The prompt is missing from the saved screenshot. | A page screenshot may capture webpage content rather than browser UI. | Verify the capture surface and browser/version. Do not infer prompt presence from a page-only screenshot. |
| Images or results appear incomplete. | The capture ran before asynchronous content or lazy-loaded elements finished. | Wait for a specific result selector or loading indicator to disappear; use a bounded timeout. |
| Screenshots differ every run. | Coordinates, browser, viewport, permission history, dynamic content, or timing changed. | Record and fix those conditions; wait for visual stability and isolate volatile areas. |
| Full-page screenshots are unexpectedly long or slow. | The page is long or loads content as it scrolls. | Capture only the relevant element or viewport when possible; wait for lazy content only if it belongs in the monitor. |
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. For a page that renders useful content without needing a configured browser geolocation permission, make one GET request to capture it. The API accepts screenshot options; see the ScreenshotNeo API documentation for the complete parameter list.
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,
)
r.raise_for_status()
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 accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, and failed loads are not billed, and cache hits cost nothing; response headers report the page verdict and billing status. An 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 a month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
9. FAQ
Can a screenshot API reproduce a browser geolocation prompt?
Do not assume it can. A prompt is browser UI, and prompt behavior depends on the actual browser environment. Validate prompt-visible capture in the browser and version used by your monitor.
Should I monitor by address or coordinates?
Use explicit latitude and longitude when the site’s behavior is driven by browser geolocation. Keep them fixed for a baseline and label the expected location state.
When should I use a full-page screenshot?
Use one when below-the-fold content is part of the check. For a prompt or a single location-results component, viewport or element capture is often a more focused signal.
Can I change location without opening a new browser?
Playwright documents updating geolocation for pages in the same browser context. Keep separate expected screenshots for each location you monitor.


