
An n8n wrong-country run is a workflow that returns HTTP 200, writes rows, and still stored the catalog of a different market than the one you asked for. Status 200 is a transport fact. It is not a geo check.
Short example. You test the HTTP Request node in the editor through -country-us. The node is green. You schedule the same canvas as a DE job without changing Options → Proxy. At 02:00 it still exits the US and stores dollar prices. n8n has nothing to flag: the request succeeded.
The rest of this page is the diagnostic: the same public URL, two country usernames, a body class, and a Jaccard overlap on (title_norm, price, currency). It is free to cite. This article does not publish first-party overlap percentages. We did not measure a live US-versus-DE catalog. Re-run before you cite a number.
[!NOTE] How to read this page. The two-country protocol, the column schema, and the overlap formula are the citable artifacts. Reuse them with attribution to Aethyn and a link back here. Do not attribute invented percentages to this page. The numeric walk-through is labeled fictional.
Copy-paste for the HTTP Request Proxy field lives on how to use residential proxies with n8n. A real browser, when the page is JavaScript, is Playwright with residential proxies.
Two-country protocol
Hold URL, language, device class, and collection window constant. Change only the country on the proxy username. Use two HTTP Request nodes (or one node run twice). Options → Proxy is a full HTTP URL with a scheme. Official n8n docs: that option is an HTTP proxy and takes precedence over HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY. Do not put a SOCKS5 URL in that field.
Constants for this walk-through (replace with a public URL you are allowed to collect):
| US leg | DE leg | |
|---|---|---|
| Target URL | https://www.example.com/catalog | same |
| Proxy host | proxy.aethyn.io:2099 | same |
| Username | aethyn-XXXXX-country-us | aethyn-XXXXX-country-de |
| Proxy URL | http://aethyn-XXXXX-country-us:PASSWORD@proxy.aethyn.io:2099 | http://aethyn-XXXXX-country-de:PASSWORD@proxy.aethyn.io:2099 |
Accept-Language | en-US | de-DE |
Premium country is the right pool when the object is a national catalog and currency. Elite city is the wrong lever unless the hypothesis is local stock — see Premium versus Elite below. URL-encode the password if it contains @, :, or /.
- Verify each exit first. GET an IP lookup through the same Proxy string, before the catalog URL. Store
exit_ip,resolved_country,resolved_city. Ifresolved_countryis not the one you asked for, class the runwrong_geoand stop. - Fetch the catalog URL through that same Proxy string. Turn on Include Response Headers and Status. Turn on Never Error so a 403 is still an item you can classify. Timeout 20,000–30,000 ms.
- Classify the body before you insert a row.
Use the HTTP Request node for outbound requests. Whether a Code node can open sockets depends on n8n version, Cloud versus self-hosted, and task-runner / sandbox settings. Confirm against your deployment. This page treats Code as a classifier of HTTP Request output, not as a second HTTP client.
Body classes (fail-closed):
| Class | Meaning |
|---|---|
populated | The catalog you came for is present (product rows, prices, currency). |
empty | 200 or 204 with no payload, or a shell with no content nodes. |
consent | Cookie or consent wall. |
challenge | Interstitial, unusual-traffic, JS challenge HTML. |
wrong_geo | Resolved country is not what you asked for. |
http_error | Non-200, including 407 (proxy auth) and 403/429. |
Public web only. Respect robots.txt, rate limits, and Terms. This protocol samples publicly rendered pages. It is not a login, checkout, CAPTCHA, or Cloudflare-bypass recipe.
Fictional classified outputs (not a measurement)
These four rows are a teaching fixture. They are not Aethyn production data. Replace them with your run and your collected_at.
| Leg | IP lookup | HTTP | Body excerpt | Class |
|---|---|---|---|---|
| DE, good | {"ip":"192.0.2.10","country":"DE"} | 200 | product rows, €79.99 | populated |
| DE, consent | {"ip":"192.0.2.10","country":"DE"} | 200 | Before you continue | consent |
| DE, challenge | {"ip":"192.0.2.10","country":"DE"} | 200 | unusual traffic | challenge |
| DE username, US exit | {"ip":"198.51.100.20","country":"US"} | — | (do not fetch the catalog) | wrong_geo |
Store the country you landed in, not only the one you typed:
record = {
url,
requested_country, # from the username you sent
resolved_country, # from the IP lookup
resolved_city,
http_status,
body_class, # populated | empty | consent | challenge | wrong_geo | http_error
items: [{ title_norm, price, currency }], # only when body_class == populated
collected_at
}

Fictional overlap (not a measurement)
For two populated runs of the same URL, build a set of tuples (title_norm, price, currency) per country. Jaccard overlap is |A ∩ B| / |A ∪ B|. Do not average in empty, consent, or challenge rows — those are different documents. Soft 200s poison overlap the same way they poison other scraper datasets.
Fictional sets. US: {(headphones, 79.99, USD), (chair, 249.00, USD), (bottle, 18.50, USD)}. DE: {(headphones, 79.99, EUR), (chair, 249.00, EUR), (bottle, 16.99, EUR)}. Intersection is empty because currency is part of the tuple, so Jaccard is 0 / 6 = 0. That is the point of keeping currency in the key — a euro price is not a dollar price. Do not cite 0 as Aethyn data. Put your collected_at on the slide.
Once two HTTP Request nodes can produce classified rows, wire the rest of the canvas with how to use residential proxies with n8n. Trial: start free.
Troubleshooting
| Symptom | First check |
|---|---|
| Correct status, wrong country | Verify the exit IP and resolved_country before the catalog GET |
| Country changes between pages | Same -session-<id>-lifetime-N on every node in that walk |
| HTTP 200 but no product rows | Classify the body (empty / consent / challenge) — do not store prices |
| HTTP 407 | Proxy credentials, URL-encoding, and HTTP port (2099 Premium / 5499 Elite) |
| Correct exit, wrong currency | Storefront host, Accept-Language, cookies, and any site country query parameter |
Three canvas mistakes produce the first two rows. They share a green 200.
One proxy string on every node. The editor test used a US username. The schedule is DE. Nothing in n8n notices.
Rotate mid-pagination. No session id. Page one is DE, page two is US. A cookie minted on IP A is sent from IP B.
Locale versus exit. Accept-Language: de-DE is an HTTP header. A storefront may also key off the host (example.de versus example.com) or a site-specific query parameter (for example ?country=DE on that site — not a universal gl= flag). Those signals are not interchangeable. A German header through a US exit is a contradictory session. Match the ones you control, then trust resolved_country.

Rotate (omit -session-) when each item is an independent URL. Sticky (-session-<id>-lifetime-N, 1–1440 minutes, default 30) when page two must see the same exit as page one. Put that exact Proxy URL on every node in the walk, then drop the session id. Sticky holds a rotating-pool residential IP. It is not a dedicated address.
On n8n Cloud, Options → Proxy on the node is the path you have. On self-hosted n8n, HTTP_PROXY / HTTPS_PROXY / ALL_PROXY apply to the whole process unless you set NO_PROXY. The node's Proxy field still wins for that node. N8N_PROXY_HOPS is a reverse-proxy setting in front of n8n itself. It is not the HTTP Request proxy.
Premium versus Elite
Country catalog and currency: Premium HTTP 2099. City or ISP: Elite HTTP 5499. Same host proxy.aethyn.io. The HTTP Request Proxy option is an HTTP proxy URL, so use those HTTP ports, not SOCKS5 1099 / 3499.
Two different failures get collapsed into “it ignored my city.” Keep them apart:
| Case | What the username asked | What the docs say happens | What you store |
|---|---|---|---|
| Unsupported combo | -city- or -isp- on Premium (port 2099) | City and ISP are Elite-only. Asking for a city on Premium is refused (targeting, Browser MCP). | Do not label the row as that city. Rebuild on Elite 5499 or drop the city. |
| Valid Elite target, no matching exit | -country-us-city-chicago on Elite 5499 | Closest available match; if none, the tunnel falls back to the country (targeting). | requested_city and resolved_city. If they disagree, class wrong_geo. |
This page did not capture a live 407 body for the Premium-plus-city case. Treat the published refusal as the contract, then verify with an IP lookup on your credential. Asking for a city is not landing there.
http://aethyn-XXXXX-country-de:PASSWORD@proxy.aethyn.io:2099
http://aethyn-XXXXX-country-de-session-wf1-lifetime-30:PASSWORD@proxy.aethyn.io:2099
PAYG gigabytes never expire. Premium versus Elite is location and harder anti-bot, not “stealth.” If the body class is challenge on HTTP Request, move the client (a real browser through the same username), not the country string. Least expensive client that produces the document: curl_cffi vs requests vs Playwright.
What this page is not
It is not an n8n install guide. It is not a copy-paste for every community Playwright node — credentials go in username and password fields; the rest is the Playwright integration. It is not a claim that a residential IP unlocks a storefront, clears CAPTCHAs, or bypasses Cloudflare. It is not a published US/DE overlap percentage.
n8n wrong-country FAQ
Does this page publish US versus DE catalog overlap percentages?
Why does rotating the IP mid-pagination change the country?
Should every n8n node share one proxy URL?
Is locale the same as the proxy country?
Guides, integrations & docs
Continue reading

How to Use Residential Proxies with Playwright (2026)
A Playwright residential proxy is a browser context whose traffic exits through an ISP-assigned household IP. Credentials go in fields, rotation is a new context, and locale must match the exit.

HTTP 200 Access Denied: Soft Blocks That Poison Scrapers
Status 200 can still be Access Denied or an AkamaiNetStorage unavailable page. Build title and content asserts so soft blocks stop looking like successful scrapes.

curl_cffi vs Requests vs Playwright for Web Scraping (2026)
Use the least expensive client that reliably produces the required document. A three-client test — requests, curl_cffi, Playwright — on one residential exit. Record status and body class, not a pass-rate table.
Pin the country on the username, not in a hope.
Premium HTTP 2099 for country jobs. Elite 5499 when the target scores the city. Sticky 1–1440 minutes on a rotating pool. Free trial, no card.