E-commerce

Compare a Product Page Across Locations

Retail sites often change what they show based on where the request comes from. That is useful when you are checking localized messaging, market selectors, shipping copy, or regional pricing — but it is hard to do from a single office IP.

This example uses the Scraper API to fetch the same product URL twice: once through a United States residential proxy, and once through a United Kingdom residential proxy. Then we compare the Markdown.

What you will get

By the end, you will have:

  • Two Markdown extracts of the same Nike product page
  • Confirmed metadata.proxy.country values for each run
  • A simple side-by-side check for location-specific content

Target page

https://www.nike.com/t/air-force-1-07-mens-shoes-jBrhbr/CW2288-111

Why this page works well for a demo:

  • It is a real public product detail page
  • It responds differently by exit country
  • In our captured UK run, Nike surfaced an explicit location banner

Setup

You need a Geonode API key and Python with requests installed.

pip install requests
export GEONODE_SCRAPER_API_KEY="YOUR_API_KEY"

PowerShell:

pip install requests
$env:GEONODE_SCRAPER_API_KEY="YOUR_API_KEY"

Keep your API key private

Do not hardcode the key in source or commit it to git. Use an environment variable or a local .env file.

The idea

Keep everything identical except the country:

{
  "url": "https://www.nike.com/t/air-force-1-07-mens-shoes-jBrhbr/CW2288-111",
  "formats": ["markdown"],
  "render_js": true,
  "processing_mode": "sync",
  "proxy": {
    "country": "US",
    "type": "residential"
  }
}

Then repeat the same request with "country": "GB".

That isolates geo-targeting as the only intentional variable.

FieldWhy it is set
formats: ["markdown"]Easy to read and compare
render_js: trueNike's PDP is JS-heavy
processing_mode: syncWait for the full result in one response
proxy.countryForce US or GB exit
proxy.type: residentialBetter fit for consumer retail sites

Implementation

import json
import os
from pathlib import Path

import requests

API_KEY = os.environ["GEONODE_SCRAPER_API_KEY"]
URL = "https://www.nike.com/t/air-force-1-07-mens-shoes-jBrhbr/CW2288-111"
COUNTRIES = ["US", "GB"]
OUT = Path("output")
OUT.mkdir(exist_ok=True)


def extract(country: str) -> dict:
    response = requests.post(
        "https://scraper.geonode.io/v1/extract",
        headers={
            "X-Api-Key": API_KEY,
            "Content-Type": "application/json",
        },
        json={
            "url": URL,
            "formats": ["markdown"],
            "render_js": True,
            "processing_mode": "sync",
            "proxy": {
                "country": country,
                "type": "residential",
            },
        },
        timeout=300,
    )
    response.raise_for_status()
    return response.json()


results = {}

for country in COUNTRIES:
    result = extract(country)
    markdown = result["data"]["markdown"]
    path = OUT / f"nike_af1_{country}.md"
    path.write_text(markdown, encoding="utf-8")

    results[country] = {
        "proxy": result["metadata"]["proxy"],
        "tokens_charged": result["tokens_charged"],
        "markdown_length": len(markdown),
        "has_uk_banner": "We think you are in United Kingdom" in markdown,
        "path": str(path),
    }

    print(country, results[country])

us = (OUT / "nike_af1_US.md").read_text(encoding="utf-8")
gb = (OUT / "nike_af1_GB.md").read_text(encoding="utf-8")

summary = {
    "target_url": URL,
    "markdown_differs": us != gb,
    "results": results,
}
(OUT / "geo_comparison.json").write_text(
    json.dumps(summary, indent=2),
    encoding="utf-8",
)

print("markdown_differs:", summary["markdown_differs"])

Run it:

python geo_targeted_extract.py

You should get:

  • output/nike_af1_US.md
  • output/nike_af1_GB.md
  • output/geo_comparison.json

What you get in the response

A successful sync extract looks like this shape:

{
  "data": {
    "markdown": "# Nike Air Force 1 '07\n\n$115\n..."
  },
  "metadata": {
    "url": "https://www.nike.com/t/air-force-1-07-mens-shoes-jBrhbr/CW2288-111",
    "render_js": true,
    "http_status": 200,
    "duration_ms": 9069,
    "formats": ["markdown"],
    "proxy": {
      "country": "US",
      "type": "residential"
    },
    "processing_mode": "sync",
    "headers": {},
    "wait_config": null
  },
  "tokens_charged": 1
}

You mainly care about:

FieldMeaning
data.markdownClean page content for that country
metadata.proxyCountry and proxy type actually used
metadata.http_statusStatus from the target site
metadata.duration_msHow long the extract took
tokens_chargedTokens billed for the request

You do not get structured product fields such as name, price, or sku. Those must be parsed from data.markdown if you need them.

Captured US vs GB results

From the live runs used for this example:

USGB
HTTP status200200
tokens_charged11
metadata.proxy.countryUSGB
metadata.proxy.typeresidentialresidential
metadata.render_jstruetrue
metadata.duration_ms906913864
Markdown length6781742453
Markdown differsyesyes

Both returned the product:

# Nike Air Force 1 '07

$115

The UK extract also included this location banner:

# We think you are in United Kingdom. Update your location?

That banner was not present in the captured US extract.

Read the result carefully

Geo-targeting does not guarantee a currency change. In this captured run, both markets still showed $115. The useful proof is that the page reacted to exit country — here via Nike's location banner and different Markdown overall.

How to judge success

  1. Proxy appliedmetadata.proxy.country matches what you requested
  2. Content extracteddata.markdown contains the product page
  3. Meaningful difference — the two Markdown files differ, or one country shows a clear market signal

Do not judge only on price. Banners, market pickers, shipping text, and locale strings all count.

When to use this pattern

Use geo-targeted extract when location changes the page you care about:

  • Market localization QA
  • Competitor monitoring by region
  • Shipping / availability messaging checks
  • Detecting country-specific offers or banners

If location does not matter, omit proxy.country and let the API use default routing.

Next

Once this pattern is working, natural follow-ons are:

  • Batch-extract a list of SKUs from one country
  • Map a storefront, filter product URLs, then batch-extract them
  • Combine proxy.country with custom headers such as Accept-Language

On this page