Use case · Brand protection
Check listings from a shopper’s IP. Keep the evidence.
Counterfeits, unauthorised resellers and below-MAP offers are often shown only to consumer connections in the region they target — not to an office network or a datacenter range. Load the listing from a residential or carrier IP in that market, keep one IP for the whole capture, and store the exit, the time, the full-page screenshot and the HTML.
Pay per GB · No subscription · Prices in EUR, excl. VAT
- listing
- lst-48211
- requested
- de · berlin
- session
- k3f9a1x2 · 30 min
- exit_ip
- 203.0.113.57
- exit_country
- DE
- same_ip_throughout
- true
- captured_at
- 2026-09-14T09:12:41Z
- full-page.png
- 1440 × 5120 px
- html_sha256
- 3f9c2e4a…d1b7
- finding
- offer below MAP
- €2.00
- per GB on ARC Fast, excl. VAT
- 185+
- countries, city targeting
- 4G/5G
- carrier IPs in DE, GB, US, JP
- Never
- expires — no subscription, EUR invoices
The problem
What a capture from the wrong address misses
None of this is exotic. It is what happens when a listing is fetched from the wrong kind of address — or from more than one.
Your office IP is not a shopper
A corporate range or a VPN exit is not a consumer connection, and some sellers show it a generic page, an empty result or a different seller list. The listing your customers see never makes it into your report.
Datacenter ranges get a different page
Cloud and hosting ranges are easy to recognise, and some sites answer them with a reduced page, a consent wall or a challenge. A capture from there documents what an automated visitor got, not what a buyer sees, and that is easy to dispute.
The price is regional
Minimum advertised prices are set per market, and so are the violations. An offer shown only to visitors in Poland is found only from an IP in Poland. Country and city are two tokens in the username.
The offer is shown on phones
Some sellers show a different page or price to visitors on a carrier network. A residential line does not see it; a 4G/5G IP in that country does.
The IP changes mid-capture
If the exit check, the page load and the screenshot leave from three addresses, the record describes three visits. A sticky session holds one IP for the whole capture, and a second exit check shows that it did.
The screenshot has no provenance
A picture on its own is a picture. The requested market, the exit IP and country, the session handle, a UTC timestamp and a hash of the stored HTML turn it into a record someone can check a year later.
Setup
Recommended setup
Start on ARC Fast with one sticky session per capture. Move the captures where a failure is expensive to ARC Ultra, and use ARC Mobile where the carrier view is the point.
| Plan | Role | Session | Targeting | Price |
|---|---|---|---|---|
ARC Fast Rotating residential | Default Residential exits in 185+ countries with city targeting, one IP per capture, and the steepest volume ladder we sell. Sweeps and captures both start here. | Sticky, 10–30 min per capture | Country + city | €2.00 / GB €1.12 at 1 TB (−44%) |
ARC Ultra Premium residential | When a failed capture is expensive The premium residential pool, for the targets where ARC Fast leaves you with failed captures you cannot explain. It is the priciest of the three rotating pools, so route only those through it. | Sticky | Country + city | €3.50 / GB €2.17 at 1 TB (−38%) |
ARC Mobile Mobile 4G/5G | Carrier view Real 4G/5G carrier IPs for offers shown only on a phone network. 4 countries, no city targeting. Lines are generated for you on mobile.arcproxies.io, in the dashboard or over the API — nothing to compose. | Sticky, up to 60 min | Country (DE, GB, US, JP) | €3.50 / GB €3.15 at 1 TB (−10%) |
http://USERNAME _pool-arcfast _country-de _city-berlin _session-k3f9a1x2 _sesstime-30:PASSWORD@ proxy.arcproxies.io:8000http://USERNAME _pool-arcultra _country-fr _city-paris _session-k3f9a1x2 _sesstime-30:PASSWORD@ proxy.arcproxies.io:8000Prices are list prices in EUR, excl. VAT. Volume discounts apply automatically at checkout — full ladder on the pricing page.
Capture
One capture, one IP, one record
Five steps, always in this order, each leaving something in the record. The capture snippets below do all five; use this to check any other tool you wire in.
- 1
Open a session
Mint one handle for this capture and put it in the username next to the market. Every request until the browser closes leaves from that one IP.
- _session-k3f9a1x2
- _sesstime-30
- 2
Record the exit
Through the same session, load an IP-echo endpoint and store the address and country it reports, beside the market you asked for.
- exit_ip 203.0.113.57
- exit_country DE
- 3
Load the listing
Same session, the market's locale, an ordinary desktop viewport. Let the page finish loading — this is the page the record is about.
- locale de-DE
- viewport 1440×900
- 4
Take the artefacts
Full-page screenshot, rendered HTML and a UTC timestamp, at the same moment. Then read the exit again: the same address means one IP served the whole capture.
- full-page.png
- page.html
- captured_at
- same_ip_throughout
- 5
Hash and store
Hash the HTML at capture time, write the record beside the files, and move all of it to the storage your legal team already keeps evidence in.
- sha256(page.html)
- → record.json
Code
Capture and sweep, in your stack
Each snippet uses the tool's documented proxy option. Replace USERNAME and PASSWORD with the credentials from your dashboard and the IP-echo URL with one you trust; everything after USERNAME is targeting, and the session handle is minted per capture.
import { createHash, randomBytes } from "node:crypto"import { mkdir, writeFile } from "node:fs/promises"import { chromium } from "playwright"const SERVER = "http://proxy.arcproxies.io:8000"const IP_ECHO = "https://your-ip-echo.example/" // returns { ip, country } for the callerexport async function capture(listingId, url) { // One handle per capture: every request below leaves from the same // residential IP in Berlin, held for 30 minutes. const session = randomBytes(4).toString("hex") const browser = await chromium.launch() const context = await browser.newContext({ proxy: { server: SERVER, username: `USERNAME_pool-arcfast_country-de_city-berlin_session-${session}_sesstime-30`, password: process.env.ARC_PASSWORD, }, locale: "de-DE", viewport: { width: 1440, height: 900 }, }) const page = await context.newPage() const exit = async () => (await page.goto(IP_ECHO)).json() const before = await exit() // the exit, before the page await page.goto(url) const capturedAt = new Date().toISOString() const html = await page.content() const dir = `evidence/${capturedAt.slice(0, 10)}/de-berlin/${listingId}` await mkdir(dir, { recursive: true }) await page.screenshot({ path: `${dir}/full-page.png`, fullPage: true }) await writeFile(`${dir}/page.html`, html) const after = await exit() // and after: same session, same IP? const record = { listing: listingId, url, requested: { country: "de", city: "berlin" }, session, exit_ip: before.ip, exit_country: before.country, same_ip_throughout: before.ip === after.ip, captured_at: capturedAt, html_sha256: createHash("sha256").update(html).digest("hex"), } await writeFile(`${dir}/record.json`, JSON.stringify(record, null, 2)) await browser.close() return record}The proxy goes on the context, so one browser can run several captures with different handles. The exit is read through the same session before and after the page — two matching addresses are what tie the screenshot to one IP in the requested country.
Before it becomes evidence
- One _session- handle per capture, lowercase letters and digits. Store it in the record; never reuse it for another listing.
- Read the exit IP and country through the same session, before the page and again after it.
- Hash the HTML at capture time and keep the hash with the files. Timestamps in UTC.
- Public, logged-out pages only — the page a shopper sees without an account.
- Keep the password and the API key in environment variables, never in the record.
- Move the evidence off the runner into the storage your legal team already uses.
The full request and response shapes are in the API reference.
Works with anything that takes a proxy URL
Playwright
- Puppeteer
- Selenium
- Python requests / httpx
- Node.js
- Scrapy
- n8n
- curl
Illustration
What a daily full capture of 300 listings in 6 markets costs
An illustration with round numbers — your pages, payloads and retry rate will differ. The arithmetic is the real price ladder.
Assumptions
- Listings watched
- 300
- Markets
- 6
- Captures per listing and market
- 1 a day, 30 days
- Full-page render, images included
- 3 MB
- Retries and redirects
- +10%
- Bandwidth per month
- ≈ 179 GB
On ARC Fast
€243.44per month, excl. VAT
179 GB bought in one purchase at €1.36 / GB (−32% volume rung, applied automatically).
The same 179 GB on ARC Ultra: €463.61 at €2.59 / GB. Route only the jobs that need it through the pricier pool.
That is the upper bound: every listing rendered in full, every day. Sweep the HTML first (0.5 MB a page) and render only the 5% that look wrong, and the same month is about 39 GB — €71.76 on ARC Fast. The screenshot itself adds nothing to the bandwidth line; the images and fonts on the page do, and a capture should keep them, because they are part of what the shopper saw.
Bandwidth never expires, so a bigger single purchase is only ever cheaper per GB. See the ladder.
FAQ
Procurement questions
Something not covered? Write to contact@arcproxies.io.
Get started
Find the listings your customers are finding.
Create an account, and code WELCOME15 takes 15% off your first bandwidth purchase, up to 25 GB. No subscription, no sales call, and the gigabytes never expire.
Related
Other things people route through ARC
Price monitoring
See the price a shopper in Berlin, Lyon or Chicago sees. ISP bandwidth at our lowest price per GB for HTML checks, residential where a marketplace is strict.
Read moreTravel fares
Airline, hotel and rail fares change with the point of sale. Query each market from an IP inside it so the fare you store is the fare a traveller is quoted.
Read moreReviews & changes
Watch reviews, terms, stock and landing pages on a schedule, from the country the page is written for — and catch the change on the run it happens.
Read moreWeb scraping
A second provider that just works — Scrapy, requests, Crawlee or Playwright, self-serve, no sales call, bandwidth that never expires.
Read more