Price Monitoring with Proxies: Getting Prices You Can Trust

Personalised, geo-varied and cached prices make single-IP scrapes wrong. How to collect competitor prices that reflect what buyers actually see.

Price monitoring exists to answer one question: what does a buyer see when they look at this product right now? Repricing engines, buy-box strategies and margin reports all sit downstream of that answer, which means a wrong answer is worse than no answer at all. A repricer fed a stale or personalised competitor price will cheerfully undercut a number nobody is actually charging, and it will do so at scale, automatically, until someone notices the margin report.

This guide is about the ways price data goes wrong before it ever reaches your database, and how vantage point, product matching and observation design fix them. The proxy is the smallest part of the system. It is also the part that determines whether everything downstream is measuring reality.

The price on the page is an answer to a question you did not ask

The naive model of an e-commerce page is that it has a price and your scraper fetches it. Modern retail does not work that way. The number rendered into the page is computed per request, and several inputs to that computation come from the request itself:

The consequence is that a single scraping server in one datacenter does not observe "the price". It observes the price served to one unusual visitor: an anonymous, cookieless client on a hosting-range IP, which is close to the least representative shopper a retailer ever sees. Some sites respond to exactly that profile by serving a deliberately degraded page, a default national price, or a block page dressed up as an out-of-stock notice.

Fixing the vantage point is what proxies are for here. Observing from residential exits in the buyer's own market, with the country pinned per request, produces the page a real shopper in that market receives. Observing the same product from two or three distinct exits in the same market tells you whether the price is stable or you have landed in an experiment. For catalog-scale coverage across many retailers, rotating access spreads the requests so no single address builds up a scraping profile.

Product matching: the identity problem is harder than the scraping

Before a price comparison means anything, both sides must refer to the same thing, and product identity across retailers is genuinely messy:

Get the matching layer wrong and the proxy layer is irrelevant: you will be comparing perfectly-collected prices of different things.

Currency, tax and the display trap

Cross-market comparison adds a second identity problem: the identity of the number. A figure scraped in Germany typically includes VAT because consumer-price display rules there require it; the equivalent US figure excludes sales tax because tax is added at checkout by delivery address. Comparing the two raw is a built-in error the size of the tax rate.

Decide, per market, what the collected number represents (tax-inclusive shelf price, tax-exclusive base, delivered price with shipping), and record that decision with the data. Store the currency code with every observation and convert at analysis time with a dated exchange rate, never at collection time, so a currency movement is not silently baked into a "price change". And beware sites that geo-detect and convert prices for foreign visitors: a converted price is the site's estimate at its own chosen rate, not the market price locals pay. This is another argument for in-market exits: a shopper in Madrid sees euros priced for Spain, so your Spanish observations should come from Spanish exits, not from a US address with a currency banner. Before committing a market to a schedule, it is worth checking that the coverage supports the granularity you want: the pages for Spain, Germany and the United States each list the cities currently targetable there, and the US in particular is really several markets, since tax, shipping cutoffs and stock differ by state.

The silent failure: recording a cached or personalised page as the market

The failure mode that deserves the most paranoia is not being blocked. Blocks are loud. The dangerous outcome is a page that renders perfectly, parses cleanly, and carries a number that is not the current market price, because it came from a cache, or because it was personalised to your scraping profile.

Caching happens at several layers you do not control: the retailer's CDN serving a stale edge copy, an intermediate cache keyed without the pricing cookie, or the retailer's own page generator running behind its pricing engine's update cycle. Personalisation is the mirror image: the page is fresh, but fresh for the visitor you appeared to be.

Neither failure announces itself, so the collection system has to be designed to catch it:

Stale versus changed: the data model does the work

The design decision that separates robust price intelligence from a brittle scraper is refusing to store "the current price" as a mutable field. Store observations: product identity, variant, seller, raw price string as rendered, parsed value, currency, tax basis, exit country, timestamp, and a fetch outcome. Derive "current price" and "price changed" as queries over observations.

This buys you three things. First, failed or suspect fetches stop masquerading as data: an observation with a block outcome is recorded and excluded, instead of the previous price silently persisting as if reconfirmed. Distinguishing "we saw the same price again" from "we have not successfully looked recently" is the whole difference between stale and unchanged, and only an observation log can make it. Second, you can re-parse history when a retailer changes its page layout, because the raw evidence is retained. Third, change detection becomes debounceable: require two consecutive confirming observations before emitting a change event, and flapping caused by experiments or offer rotation stops paging anyone.

Scheduling: frequency should follow volatility

Fetching every product at the same fixed interval wastes most of your bandwidth on items that never move and under-samples the ones that move hourly. Let the observation history drive the schedule: products with recent changes, promotion flags or marketplace offer churn get sampled more often; the long tail that repriced twice last quarter gets sampled daily or weekly. Around known volatility events (sale seasons, a competitor's announced promotion), temporarily promote whole categories.

This is also where request-rate discipline lives. A monitoring workload runs continuously against the same set of retailers, which makes it more detectable over time than a one-off crawl. Spread requests across the day rather than firing the whole catalog at the top of the hour, randomize ordering, and keep per-retailer concurrency low. If a retailer starts serving blocks, backing off is not politeness; it is protecting the vantage point your data quality depends on. The mechanics of spreading load across exits are covered in the IP rotation guide, and how many proxies you need works through sizing the pool against catalog size and fetch frequency.

Choosing the access layer

Not every retailer requires the same machinery, and paying for residential bandwidth to scrape a site that happily serves datacenter ranges is money spent on nothing. A workable ladder:

Per-product-per-market cost is the metric to watch: bandwidth-billed residential collection rewards lean fetches, so strip images and third-party scripts from your requests where the price survives without them.

Price intelligence is one of a family of in-market observation workloads that share this access layer while differing in what corrupts them. Ad verification faces a counterparty with an incentive to show the observer something flattering; rank tracking fights contamination from the measurer's own search footprint. Price monitoring's enemy is subtler than either: nobody is deceiving you on purpose; the infrastructure is just answering a differently-shaped question than the one you meant to ask.

The part that is your call

A note on boundaries. Collecting publicly displayed prices is a long-established commercial practice (retailers do it to each other constantly), but the terms of service of individual sites, and the law of the places you and they operate, are not uniform and not this article's to interpret. Read the terms of the sites you monitor, honor explicit technical signals where you decide they apply, and take advice where the stakes justify it. What this guide describes is technical practice; whether and where to apply it is a judgment that stays with you.

Start small: one market, one retailer set, canary products from day one, and an observation log rather than a price field. The free tier is enough to prove the pipeline end to end (matching, parsing, double-observation) before scaling a catalog onto it.