ScreenshotNeo

BlogHow-to

How to Use Selenium to Screenshot Product Pages with Location-Based Pricing

Emulate browser geolocation, wait for a product page’s regional state, and save a reproducible screenshot with Selenium.

By the ScreenshotNeo team4 October 20269 min read

Selenium can emulate browser geolocation, grant a page permission to use it, wait for a product page to show its regional state, and save a screenshot. This is a controlled browser observation: geolocation alone does not guarantee a retailer will change its price. The site may use a selected delivery region, account, cookies, network location, or other inputs. Verify what the page actually displays and record the conditions with each capture.

The example below uses Selenium’s Python WebDriver BiDi APIs. Install Selenium and a supported browser, enable BiDi, set coordinates and permission for the retailer’s origin, navigate, wait for page-specific indicators, and save a PNG. Check the API documentation for your installed Selenium and browser versions because BiDi support and API details can change.

1. Install Selenium and prepare the browser

Install the Python binding:

python -m pip install selenium

Selenium WebDriver controls a real browser through a browser-specific driver. Use a supported browser and keep the Selenium binding, browser, and driver compatible. Current Selenium setups can manage drivers automatically in common configurations; consult the Selenium getting started guide for setup details and Grid options when scaling execution.

Choose coordinates for the location you want the browser to report. Latitude must be in the range -90 to 90 and longitude in the range -180 to 180. For example, the values below correspond to a point in New York City; they do not select a retailer delivery address or prove that the retailer used those coordinates to determine a price.

2. Set geolocation, navigate, wait, and capture

Save the following as screenshot_product.py. Replace the URL, coordinates, and the two CSS selectors with values for the page you are observing. The selectors must identify a visible price and a visible region or currency indicator. The example uses explicit waits so a navigation completing is not mistaken for a finished dynamic price update.

from pathlib import Path

from selenium import webdriver
from selenium.webdriver.common.bidi.emulation import GeolocationCoordinates
from selenium.webdriver.common.bidi.permissions import PermissionDescriptor, PermissionState
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By

PRODUCT_URL = "https://shop.example/product"
ORIGIN = "https://shop.example"
LATITUDE = 40.7128
LONGITUDE = -74.0060
PRICE_SELECTOR = "[data-testid='price']"  # Replace with the retailer's selector
REGION_SELECTOR = "[data-testid='region']"  # Replace with a visible region/currency selector
OUTPUT = Path("product-location.png")

options = webdriver.ChromeOptions()
options.enable_bidi = True

# Set a stable viewport for comparisons. Adjust to the layout being captured.
options.add_argument("--window-size=1440,1000")

driver = webdriver.Chrome(options=options)
try:
    context_id = driver.current_window_handle

    # Geolocation emulation and permission are separate settings.
    driver.emulation.set_geolocation_override(
        coordinates=GeolocationCoordinates(
            latitude=LATITUDE,
            longitude=LONGITUDE,
        ),
        contexts=[context_id],
    )
    driver.permissions.set_permission(
        PermissionDescriptor("geolocation"),
        PermissionState.GRANTED,
        ORIGIN,
    )

    driver.get(PRODUCT_URL)
    wait = WebDriverWait(driver, 30)
    price = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, PRICE_SELECTOR)))
    region = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, REGION_SELECTOR)))

    # Store the visible values with the image so the configured location is
    # distinguishable from the state the page actually displayed.
    price_text = price.text.strip()
    region_text = region.text.strip()
    if not price_text or not region_text:
        raise RuntimeError("Price or region selector was visible but had no text")

    driver.save_screenshot(str(OUTPUT))
    print(f"Saved: {OUTPUT}")
    print(f"Configured coordinates: {LATITUDE}, {LONGITUDE}")
    print(f"Displayed region/currency: {region_text}")
    print(f"Displayed price: {price_text}")
finally:
    driver.quit()

Run it with:

python screenshot_product.py

The selectors are intentionally retailer-specific. Inspect the page’s DOM and choose stable attributes where possible. If a region or price appears only after an interaction, use Selenium to perform the site’s ordinary location-selection flow, then wait for the resulting visible state. Geolocation does not replace that step.

Why both geolocation and permission matter

The geolocation override supplies a browser position to the selected browsing context. The permission setting controls whether the origin is allowed to request that position. A page can show a permission prompt or behave as though location is unavailable if either part is missing or applied to the wrong context or origin.

The example targets the current window handle as the BiDi browsing context ID and grants permission for the origin. If your Selenium/browser combination rejects the context or permission call, consult the versioned BiDi APIs and examples for that environment. Do not assume the API shapes across Selenium documentation versions represent one synchronized release.

3. Choose the screenshot scope

driver.save_screenshot("file.png") captures the current browser window as a PNG. It is usually the right choice when the price and enough product and region context fit in the viewport. For a focused artifact, locate a product or price container and call its element screenshot method; include enough surrounding page context to identify what was captured.

WebDriver BiDi also documents browsing-context screenshots with an origin of viewport or document and optional clipping. A viewport capture represents the current visible screen; document capture is for content beyond that viewport. Confirm the precise Python API and browser support in the installed version before relying on document capture. Full-page behavior and element screenshots can differ by driver.

4. Make location comparisons reproducible

For each location, record the configured test conditions and the page’s observed result separately. Keep other variables as consistent as practical:

  • Product URL and SKU, including relevant variants.
  • Configured latitude and longitude, geolocation permission state, and whether the page visibly reflected the intended region.
  • Visible currency and region label, displayed price, and availability.
  • Delivery charge, displayed tax, or other price components when present.
  • Browser and driver versions, Selenium version, viewport, locale, timezone, and capture time.
  • Consent state, account state, and any region selected through the retailer’s own controls.

Do not infer a location-based price from the configured coordinates alone. Record the visible currency, region, and price as page observations. Selenium’s browser controls do not document a retailer’s pricing logic.

Locale, timezone, and other state

Selenium BiDi exposes locale and timezone override APIs in documented versions. These can make a browser test more consistent when a page uses locale or timezone, but they are not equivalent to network traffic from another country and do not guarantee a retailer will select a particular delivery region. A retailer may offer a visible country, postal-code, or delivery-location selector; use that authorized flow when it is part of the scenario being captured.

Cookies and persistent region choices

Selenium requires the browser to be on a cookie’s domain before adding that cookie. A retailer may store a selected region in its own session or cookies, but cookie names and meanings are site-specific. Prefer the visible site controls or an authorized test setup. Do not assume that editing an undocumented production cookie will set the pricing region.

For comparisons, isolate browser state between runs or deliberately reuse the same state, depending on the question being tested. Record which approach you used. Cookies, consent, account state, and prior location choices can affect what the page shows.

5. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request can return an image or PDF. For this product page, a basic request looks like this; see the ScreenshotNeo API documentation for the available parameters and response behavior.

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);

Replace the example URL with the product page. These calls capture a page; they do not set Selenium-style browser geolocation or guarantee a retailer’s location-specific pricing behavior. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture, with each step configurable. Bot checks, blank pages, and failed loads are never 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 AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.

Sign up free for 1,000 screenshots a month, with no card required.

Troubleshooting

Symptom Likely cause Fix
BiDi property or command is missing The installed Selenium binding, browser, or driver does not support the API shape in the example, or BiDi was not enabled. Upgrade to a compatible Selenium/browser/driver combination, set options.enable_bidi = True, and check the documentation matching that installed version.
Permission prompt appears or location is unavailable Permission was not granted for the retailer’s exact origin, or the geolocation override was applied to a different context. Set the override for the active context and grant the geolocation permission for the exact scheme, host, and port. Handle redirects to a different origin deliberately.
The page shows the same price in every run The retailer may not use browser geolocation for price selection, or another signal such as delivery region, account, cookie, or network location may control the page. Verify the visible region and use the retailer’s location selector if appropriate. Treat unchanged displayed prices as an observation, not proof that emulation failed.
Wait times out locating price or region The sample CSS selector does not match the page, the content is in a frame or shadow root, the product state did not load, or the page uses different markup. Inspect the DOM, update the selectors, account for frames or shadow roots, and wait on a stable visible condition. Confirm the product page did not show an error or consent interstitial.
Screenshot captures an old price or incomplete layout Navigation reached document readiness before asynchronous page updates finished. Wait for the actual price and region to update, or wait for a known loading indicator to disappear. Avoid relying only on a fixed sleep.
Screenshot is clipped or too tall The default window screenshot captures the viewport, or the page layout differs at the chosen viewport. Set a consistent viewport, scroll to the relevant section, use an element screenshot with context, or use supported BiDi document capture after checking its version-specific API.
Cookie cannot be added The browser has not navigated to that cookie’s domain. Navigate to the domain before adding it. Use only known, authorized cookie state and verify the visible result.
Driver fails to start or browser exits Browser/driver incompatibility, missing browser installation, or an environment limitation. Align versions, confirm the browser is installed, and inspect driver startup output. In containerized environments, configure the browser runtime and display/headless settings for that environment.

Performance, reliability, and cost

The main runtime cost is browser startup, navigation, and waiting for the page-specific condition. Reuse a browser session for multiple captures only when the test intentionally shares cookies and state; otherwise create isolated sessions so one location run cannot contaminate another. Avoid waiting for network idle as the only condition on pages with analytics or long-lived requests. A selector tied to the price and region is usually a more meaningful readiness check.

For reliable comparisons, pin or record browser and driver versions, viewport, locale/timezone settings, permissions, consent, account, and capture time. Save structured metadata alongside the image. Retry transient navigation failures carefully, but distinguish retries from separate observations and do not silently keep only the result that matches an expectation. For larger workloads, Selenium Grid can distribute browser execution; it adds infrastructure and session-management considerations.

Selenium itself is open-source browser automation software, but a screenshot workflow still consumes compute and browser resources. Keep the capture scope as small as the evidence requires and avoid unnecessary repeated page loads. ScreenshotNeo’s published plans are Free: 1,000 shots/month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; and Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan.

FAQ

Does changing Selenium geolocation change a product’s price?

Not necessarily. It changes the browser location presented to the page; the retailer decides whether and how to use that signal. Verify the visible region and price.

Can I use coordinates instead of selecting a delivery address?

You can emulate coordinates, but coordinates are not a delivery address. If the page requires a postal code or delivery region, use its intended selector or an authorized test setup.

Does save_screenshot capture the whole page?

It saves a screenshot of the current window. For beyond-viewport content, check whether your installed browser and Selenium BiDi API support document-origin capture.

Can I compare prices across countries with this method?

You can compare what the page displays under recorded browser conditions. Geolocation emulation does not establish network location or reveal which signals the retailer used.

Official Selenium references