Scrape product prices as shoppers in each country see them
Updated 1 Oct 2026 · Tested on 1 Oct 2026
Name a country and Skryp fetches the product page from an IP there, checks the exit first, and fails rather than substituting another country when strict mode is on. Save the fields once and refresh them on a schedule; changes come back as field-level differences.
One product, four countries
This script asks for one public product page as shoppers in South Africa, the United States, the United Kingdom and Germany see it, and converts the prices to dollars to compare them. It ran as shown:
# One product page as shoppers in four countries see it: each request leaves from a checked exit in that
# country (strict: fail rather than substitute), and prices are converted to one currency to compare.
# pip install httpx export SKRYP_API_KEY=...
import os
import httpx
API = os.environ.get("SKRYP_API_URL", "https://api.skryp.dev")
out = httpx.post(
f"{API}/v1/compare",
headers={"Authorization": f"Bearer {os.environ['SKRYP_API_KEY']}"},
json={"url": "https://store.steampowered.com/app/620/Portal_2/", "countries": ["ZA", "US", "GB", "DE"], "base_currency": "USD"},
timeout=300,
).json()
print(f"{'country':<9}{'price shown':>13}{'in USD':>9} exit used")
for row in out["rows"]:
shown = f"{row['price']:,.2f} {row['currency']}" if row.get("price") is not None else row["status"]
usd = f"{row['price_usd']:.2f}" if row.get("price_usd") is not None else ""
print(f"{row['country']:<9}{shown:>13}{usd:>9} {row['exit']['country']} ({'verified' if row['exit']['verified'] else 'not verified'}), {row['route']}")
s = out["summary"]
print(f"\ncheapest {s['cheapest']}, dearest {s['dearest']}: {s['spread_pct']}% apart; same product in every country: {s['same_product']}")
print(f"exchange rates from {s['fx']['source']}, {s['fx']['updated']}; {out['receipt']['credits']} credits")country price shown in USD exit used
ZA 20.00 ZAR 1.22 ZA (verified), http:direct
US 1.99 USD 1.99 US (verified), http:res:us
GB 1.70 GBP 2.26 GB (verified), http:res:gb
DE 1.95 EUR 2.21 DE (verified), http:res:de
cheapest ZA, dearest GB: 85.2% apart; same product in every country: True
exchange rates from open.er-api.com, Thu, 01 Oct 2026 00:02:31 +0000; 31 creditsThe same game was listed at prices that differ by more than 80% once converted, because the shop prices it per market. Each row's request left from an exit checked in that country before the page loaded; the route shows how (a plain request on Skryp's own network for South Africa, a residential IP in the country for the others). Strict mode was on: if no verified exit had been available in a country, that row would have failed instead of quietly showing another country's price.
How country proof works, and what it does not prove
- You name the country. Skryp picks a route that leaves from an IP in it: its own network where it has one, otherwise a residential or mobile IP from that market.
- The exit is checked before the page loads, by asking a geolocation service through that exit (ipinfo.io first, with fallbacks). An IP that is not in the country is skipped, not used.
- Every result says where it came from. The receipt carries the exit's country, city and network and whether it was verified, so you can store the proof next to the price. See Receipts.
- Strict mode fails rather than substitutes. Without it, Skryp may use an exit elsewhere when it cannot verify one in your country; with it, that request returns an error, at no cost.
In a test of 20 countries with strict mode on, 19 returned the page through a verified exit in the requested country[30 Sept 2026]. On 22 country-priced pages in our benchmark, the right local currency came back on 21[1 Oct 2026].
What it does not prove: a verified exit shows where the request left from, not that the site priced it correctly for that market. Sites also price by account, by cookie or by delivery address. Store the receipt with the data, check a sample by hand when a number looks wrong, and use the same_product check above to catch a country that silently redirected to a different item.
From one page to a dataset
To follow every product in a listing rather than one page, collect it once as a dataset. Skryp finds where the listing's data comes from, maps the fields you named, and keys each record by a stable value such as its URL. Then refresh it on a schedule:
# From one page to a dataset: collect every product on a listing once, refresh it on a schedule,
# and read only what changed. Re-running reuses the dataset instead of creating another.
# pip install httpx export SKRYP_API_KEY=...
import os
from datetime import datetime, timezone
import httpx
API = os.environ.get("SKRYP_API_URL", "https://api.skryp.dev")
http = httpx.Client(base_url=f"{API}/v1", headers={"Authorization": f"Bearer {os.environ['SKRYP_API_KEY']}"}, timeout=300)
NAME = "Travel books (price example)"
ds = next((d for d in http.get("/datasets").json()["datasets"] if d["name"] == NAME), None)
how = "already existed"
if ds is None:
made = http.post("/datasets", json={"name": NAME, "url": "https://books.toscrape.com/catalogue/category/books/travel_2/index.html",
"fields": ["title", "price", "availability", "url"], "max_pages": 2}).json()
ds, how = {"id": made["id"]}, f"created now for {made['receipt']['credits']} credits"
http.put(f"/datasets/{ds['id']}/schedule", json={"every_s": 86400}) # refresh daily; 0 turns it off
info = http.get(f"/datasets/{ds['id']}").json()
due = datetime.fromtimestamp(info["schedule"]["next_run"], timezone.utc).strftime("%d %b %Y %H:%M UTC")
print(f"dataset: {info['record_count']} records keyed by {info['key_field']} ({how})")
print(f"schedule: every {info['schedule']['every_s'] // 3600} h, next refresh {due}")
now = http.post(f"/datasets/{ds['id']}/refresh").json()
c = now["receipt"]["credits"]
print(f"refresh now: {now['added']} added, {now['changed']} changed, {now['removed']} removed "
f"({c} credit{'' if c == 1 else 's'})")
first = http.get(f"/datasets/{ds['id']}/records", params={"limit": 2}).json()["records"]
print(first)dataset: 11 records keyed by url (already existed)
schedule: every 24 h, next refresh 02 Oct 2026 20:52 UTC
refresh now: 0 added, 0 changed, 0 removed (1 credit)
[{'title': '1,000 Places to See Before You Die', 'price': '£26.08', 'availability': 'In stock', 'url': 'https://books.toscrape.com/catalogue/1000-places-to-see-before-you-die_1/index.html'}, {'title': 'A Summer In Europe', 'price': '£44.34', 'availability': 'In stock', 'url': 'https://books.toscrape.com/catalogue/a-summer-in-europe_458/index.html'}]A refresh compares the new records with the stored ones by key and reports what was added, changed or removed. One that fails or stops part-way never marks records as removed: a page that did not load is not a deleted product. More on this on the Datasets page.
Refresh and change events
- Schedules: hourly, every 6 hours, daily or weekly, set per dataset from the API, the dashboard or an agent's
datasettool. - Changes: each refresh records which fields changed on which records, with the old and new values, readable from the dataset's changes list.
- Webhooks: a monitor can post each change to your endpoint as it happens.
- Spending limits: each monitor has a credit cap and pauses itself when it is reached, and daily or monthly limits on an API key or the whole workspace stop everything else[2 Oct 2026].
What it costs
Measured on 1 October 2026, priced on the Standard plan ($49 a month for 150,000 credits):
| Job | Credits | Cost on Standard |
|---|---|---|
| The four-country comparison above: South Africa on Skryp's own network (1), three residential IPs (5 each) and a model extraction for each of those three (5 each) | 31 | $0.010 |
| Collecting a two-page listing the first time: finding its data, mapping the fields with a model and reading both pages (measured on a 32-product listing) | 9 | $0.003 |
| Refreshing the dataset above daily for a month, at 1 credit a refresh (a cached refresh can cost nothing) | up to 30 | up to $0.010 |
A page through a residential IP costs 5 credits, or 10 when it needs a browser, because country pricing usually means a residential exit. Advanced unblocking costs 25 credits, only when it succeeds, and failed pages cost nothing. Every workspace gets 1,000 free credits a month, on Skryp's own network; see Pricing.
When a dashboard suits you better
If you only need competitor prices for your own shop and do not want to write code, merchant tools for price monitoring, such as Prisync or Price2Spy, give you a dashboard and alerts. Skryp is for teams that want the data itself in their own systems or agents, with proof of where each price came from.
Questions
- What is price scraping?
- Collecting product prices from websites automatically, usually from competitors' product pages or marketplaces, to compare prices, track changes or set your own. Doing it by country means fetching each page as a shopper in that country sees it.
- How do you scrape prices from websites?
- Fetch each product page, extract the price, currency and availability, and store them with the time and the country you fetched from. For many products, collect the listing as a dataset and refresh it on a schedule so you only handle what changed.
- How do you build a price tracker?
- Keep a list of product pages, fetch them on a schedule, store each price with its date, and alert when a price moves. A scraping API with datasets and monitors does the fetching, comparison and alerts; you keep the history and decide what to do with it.
Evidence
Asked for 20 countries with strict country on, Skryp returned the page through an exit verified in the requested country in 19 of 20.
observed test · checked 30 Sept 2026 · One public page per country, 20 countries, strict-country requests, residential and mobile routes.
Limits: A single run of 20 pages. Exit verification proves where the request left from, not that every field on the page is correct for that market.
On 22 country-priced pages, Skryp and Firecrawl each returned the expected country's currency on 21.
observed test · checked 1 Oct 2026 · 22 regional shop pages in the 170-page benchmark.
Limits: Currency is a proxy for the right regional page, not proof that every price is correct.
Each Skryp API key can have a daily limit, a monthly limit and a maximum per page, and each workspace a daily and a monthly limit; a request that would pass one is refused with HTTP 402 before it runs and costs nothing. On 2 October 2026 a key limited to 1 credit a day read one page for 1 credit, and its next request was refused.
observed test · checked 2 Oct 2026 · Skryp's API and MCP server; limits set in the dashboard by a workspace owner or admin.
Limits: Days and months are UTC. Requests in progress count at their reserved cost, so a limit can refuse a request that would have cost less. An API key cannot change its own limits.