One screenshot from another country is a VPN and five minutes. Ten countries after every deploy is a job for an API. Pass coordinates, a timezone, and a country-level proxy in one request, and the page renders as if a real visitor from that location opened it. Below is who needs to screenshot a website from different countries, why, and how the automation works.
Catch pricing bugs before your customers do
Payment platforms like Stripe and Paddle let you set regional pricing. Different amounts for different countries. The pricing page is supposed to detect the visitor's location and show the right number. In practice, this logic breaks more often than anyone admits.
CDN caching is the most common culprit: the US price gets cached at the edge and served to visitors in Germany for hours until the TTL expires. I spent a frustrating afternoon debugging one where a geo-IP database classified a Swiss IP range as German. Swiss visitors saw euros instead of francs for weeks before a customer complained. JavaScript price switchers that choke on certain currency symbols are another classic. Unit tests don't catch any of these because the logic depends on the visitor's actual network path.
A weekly screenshot of your pricing page from 5-10 target markets catches these problems before revenue suffers. The API renders the page through a country-specific proxy, so the site sees a German IP, a Berlin timezone, and German GPS coordinates. If the price shows €45, you know the German experience works. If it shows $49, something broke.
# Verify pricing page from Germany, Japan, and Brazil
for country in "de:52.52:13.405:Europe/Berlin" "jp:35.676:139.650:Asia/Tokyo" "br:-23.55:-46.633:America/Sao_Paulo"; do
IFS=: read code lat lng tz <<< "$country"
curl -s "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://yoursite.com/pricing\
&geolocation[latitude]=$lat\
&geolocation[longitude]=$lng\
&timezone=$tz\
&proxy=http://user:pass@$code.proxy.example.com:8080\
&response_type=json" \
-H "Authorization: Bearer YOUR_API_KEY" | jq '.data.screenshot_url'
done
Run this in CI (here's the GitHub Actions setup) after every deploy that touches pricing logic. Three screenshots, three countries, under 30 seconds. The geo-screenshot feature page covers the full parameter reference if you need to fine-tune coordinates or proxy settings.
Automate GDPR banner evidence across EU countries
GDPR applies everywhere in the EU, but enforcement is fragmented. Twenty-seven member states, twenty-seven interpretations. The CNIL in France cares about reject button prominence. German regulators focus on pre-consent tracking. Spain has its own stance. Most cookie consent implementations fail compliance checks in at least one jurisdiction based on the audits I've seen.
A geo-targeted screenshot from each country shows what the production page actually renders for a visitor with that country's IP and timezone. The difference between what your consent management platform reports and what real visitors see can be surprising. Compliance teams run this monthly across 5-10 EU countries. Each capture preserves the consent banner in its initial state (before any click), proving what was shown in each jurisdiction. Pair with certified screenshots for a SHA-256 hash and timestamp that regulators actually accept as evidence.
For the full compliance monitoring workflow including scheduling and evidence trails, see the compliance monitoring use case.
Do your geo-redirects still work after that last deploy?
Your CDN or middleware redirects visitors based on IP country. US visitors stay on yoursite.com. Visitors from Germany land on yoursite.de. Brazil goes to yoursite.com.br. After a deploy, you need to know these rules didn't break. Without a way to screenshot your website from different countries, you either trust the config you just pushed or ask someone in São Paulo to check manually. Neither scales.
import requests
redirects = {
"US": {"proxy": "http://user:[email protected]:8080", "expected": "yoursite.com"},
"Germany": {"proxy": "http://user:[email protected]:8080", "expected": "yoursite.de"},
"Japan": {"proxy": "http://user:[email protected]:8080", "expected": "yoursite.co.jp"},
"Brazil": {"proxy": "http://user:[email protected]:8080", "expected": "yoursite.com.br"},
"France": {"proxy": "http://user:[email protected]:8080", "expected": "yoursite.fr"},
}
for country, config in redirects.items():
resp = requests.get(
"https://api.screenshotrun.com/v1/screenshots/capture",
params={
"url": "https://yoursite.com",
"proxy": config["proxy"],
"extract_metadata": "true",
"response_type": "json",
},
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = resp.json()["data"]
final_url = data.get("metadata", {}).get("final_url", "")
status = "PASS" if config["expected"] in final_url else "FAIL"
print(f"{country}: {status} → {final_url}")
The extract_metadata parameter returns the final URL after all redirects, so you can verify programmatically without even looking at the screenshot. The screenshot itself is useful when a redirect lands on the wrong page but the right domain.
Your ads might show the wrong creative in half your markets
Display campaigns across multiple countries have a lot of moving parts. Geo-targeting misconfigurations in the ad platform, CDN edge caching serving a German banner to French visitors, programmatic exchanges overriding your targeting rules. The ad platform's preview tool shows what should load. A geo screenshot from each target country shows what actually does.
Which banner appeared. Which language the copy is in. Whether the landing page matches the market. Three questions, one screenshot per country. Marketing teams at agencies run these captures weekly during campaigns. Some set up webhook callbacks to push screenshots into Slack channels, so the team sees every country's creative in one thread without logging into a dashboard.
Local search results shift every few blocks
Search "plumber near me" from downtown Denver and you get a different local pack than the same query from Lakewood, eight miles west. Google's local algorithm weighs searcher proximity so heavily that coordinates three miles apart produce different rankings. For local businesses and SEO agencies, guessing what the SERP shows is not an option.
GPS-level precision matters here. A country-level proxy gets you "United States." The geolocation parameter gets you "39.7392, -104.9903" — a specific street in Denver. For local pack results, that precision changes everything.
# Capture Google results for "plumber near me" from two Denver neighborhoods
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://www.google.com/search?q=plumber+near+me\
&geolocation[latitude]=39.7392\
&geolocation[longitude]=-104.9903\
&geolocation[accuracy]=100\
&timezone=America/Denver\
&full_page=true\
&stealth=true\
&response_type=json" \
-H "Authorization: Bearer YOUR_API_KEY"
Note the stealth=true. Google blocks headless browsers, so stealth mode is required for SERP captures. Without it you'll get a CAPTCHA page instead of results.
SEO agencies automate this for client reports: capture the target keyword from 5-10 locations daily, compare rankings week over week. One API endpoint, different coordinates each time.
Twelve languages, twelve ways to break on every deploy
A site with 12 language versions has 12 chances to ship a regression. Hardcoded English strings leaking into the Japanese version. RTL layout issues on the Arabic site. Currency symbols rendering as question marks. Missing translations showing [key.checkout.button] instead of actual text. Debugging across 12 locales is nobody's idea of a good afternoon.
Automated geo screenshots compress hours of manual QA into minutes. Set the proxy to route through each country, add the right Accept-Language header, and capture the key pages. You don't need to read Arabic to spot a broken RTL layout in a screenshot.
const locales = [
{ lang: 'de-DE', proxy: 'http://user:[email protected]:8080', tz: 'Europe/Berlin' },
{ lang: 'ja-JP', proxy: 'http://user:[email protected]:8080', tz: 'Asia/Tokyo' },
{ lang: 'ar-SA', proxy: 'http://user:[email protected]:8080', tz: 'Asia/Riyadh' },
{ lang: 'pt-BR', proxy: 'http://user:[email protected]:8080', tz: 'America/Sao_Paulo' },
];
const pages = ['/pricing', '/checkout', '/about'];
for (const locale of locales) {
for (const page of pages) {
const params = new URLSearchParams({
url: `https://yoursite.com${page}`,
proxy: locale.proxy,
timezone: locale.tz,
'headers[Accept-Language]': locale.lang,
response_type: 'json',
});
const res = await fetch(
`https://api.screenshotrun.com/v1/screenshots/capture?${params}`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const data = await res.json();
console.log(`${locale.lang} ${page}: ${data.data.screenshot_url}`);
}
}
One detail that trips people up: the timezone parameter doesn't set Accept-Language automatically. A browser with timezone=Asia/Tokyo still sends en-US unless you override it via headers. The headers injection docs cover the full setup.
Who runs these workflows?
Compliance and legal teams are the most common users. They capture cookie banners across EU countries monthly and pair them with certification hashes for audit trails. Volume is low (50-200 screenshots/month) but evidence requirements are strict.
E-commerce growth teams have a different rhythm. They verify pricing, promotions, and checkout flows after every deploy and during campaign launches. Five countries × 10 pages × weekly = 200 screenshots, easily within the free tier.
SEO agencies go heavier on volume, tracking local rankings from 10-20 coordinates daily per client. Often on the Pro plan for timezone emulation. QA engineers use geo screenshots as a visual regression layer for internationalization testing — not replacing functional tests, but catching layout and content issues that unit tests miss.
Limitations and workarounds
The API captures what the browser renders. A/B testing platforms that assign variants by cookie history or user ID will show whichever variant the fresh browser session gets. If you need a specific variant, set the experiment cookie via the cookies parameter.
Geolocation emulation doesn't change network-level characteristics like latency or TCP fingerprinting. For sites with aggressive bot detection (banking, ticketing), use residential proxies rather than datacenter ones. We don't bundle proxies — you bring your own from a provider like Bright Data or Oxylabs. That's an extra setup step, but it means no per-screenshot proxy surcharge.
Start with your highest-traffic geo page
Pick your most commercially important geo-dependent page — pricing, checkout, or homepage — and screenshot it from your top three markets. Compare the screenshots side by side. If the currency, language, or layout is wrong in any of them, you've found your first bug. The geo parameters work on every plan, and the 200 free screenshots/month let you test the workflow before committing. Full parameter reference in the geo-screenshot feature page.
FAQ#
Yes. The free tier includes 200 screenshots per month. Timezone emulation works on all plans. GPS coordinates require Pro, and proxy routing requires Business. No credit card needed to start.
A VPN changes your IP but still requires you to manually open a browser, load the page, and take a screenshot. The API does all of that in one HTTP request and returns the image programmatically. You can loop through 20 countries in under a minute without switching anything.
Yes. ScreenshotRun does not include managed proxies. You bring your own from providers like Bright Data, Oxylabs, or SmartProxy. The proxy parameter accepts any HTTP proxy URL. This avoids per-screenshot proxy surcharges on our side.
Three parameters work together: geolocation (GPS coordinates), timezone (IANA timezone like Europe/Berlin), and proxy (HTTP proxy URL for IP-level country routing). Use one, two, or all three depending on what the target site checks. Most sites only check IP, so proxy alone is often enough.
Yes. Add extract_metadata=true to your request. The response includes the final URL after all redirects, so you can check whether the redirect landed on the expected domain without looking at the screenshot.