How do you build a price comparison tool with live product data from multiple stores?

A price comparison tool has four parts: a way to find offers for a product across stores, a matcher that decides which offers are the same item (by GTIN, then brand and model number), a normalizer that compares like with like (same variant, currency, sale and shipping terms), and a refresh loop that re-checks a price before anyone sees it. You can scrape each store and build all four, use an extraction API for the fetching, or start from a product data API that already searches and normalizes many stores, and put your matching, ranking and interface on top.

Last updated · Vendor facts checked

Step 1

Decide what you are comparing

Identical branded goods (electronics, beauty, toys, appliances, books) carry manufacturer identifiers, so the same item can be matched across stores and compared on price. Fashion and home goods are often store-exclusive or sold under different names, so a tool in those categories compares similar products rather than identical ones. Choose before you build: the matcher, the data you need and the interface all follow from it.

Either way, each row in your comparison needs the same fields:

  • the store and the product URL a shopper will land on;
  • the exact variant (size, color, capacity) the price is for;
  • the current price, the original price if it is on sale, and the currency;
  • stock for that variant;
  • shipping and tax terms when known;
  • when the price was last checked.

Step 2

Find candidate offers across stores

There are four common ways to discover where a product is sold, and most tools combine two:

  • Affiliate network feeds (CJ, Rakuten Advertising, Awin, Impact). Participating merchants publish product feeds with prices and identifiers, and you earn commission on click-outs. This is how many comparison sites start. Feeds refresh about daily and cover only merchants in the network.
  • Store sitemaps and product feeds. Sitemaps list product URLs but not prices, so you still fetch each page.
  • Each store's own site search, queried by product name or model number. Accurate for that store, but it is one integration per store.
  • A cross-store product search API, which returns candidate offers from many stores for one query.

Google's Merchant API (formerly the Content API for Shopping) manages a merchant's own listings; it doesn't return other stores' prices.

Step 3

Match identical items before comparing prices

A wrong match is worse than a missing one: it tells someone a different item is cheaper. Match with a ladder, strongest key first:

  • GTIN (UPC or EAN), left-padded to 14 digits with the check digit validated.
  • Brand + manufacturer part number (MPN), with punctuation stripped. Model numbers in titles (WH-1000XM5, KSM150PS) are a good source when the MPN field is empty.
  • Brand + title tokens + key attributes (capacity, color, pack size), scored, with a threshold tuned on labeled pairs. Below the threshold, show the offer as "similar", not "same".

Match at the variant level. Stores often put several sizes or capacities on one page, and those are different prices. See how to normalize product data across retailers for the full matching and variant model.

Step 4

Compare like with like

Price comparison pitfalls and how to handle them
PitfallWhat to do
Variants priced differently (XL, 256 GB)Compare the same variant across stores, never the page's headline price
Sale vs. regular priceStore both; rank by the current price and show the discount separately
Region and currencyFetch prices as a shopper in the target country sees them; don't silently convert currencies
Shipping and taxUS prices usually exclude sales tax and EU prices include VAT; label shipping as unknown when it is
Out of stockShow it, ranked below in-stock offers; treat unknown stock as unknown, not in stock
Member, coupon and cart pricesLeave out prices that need a login or code, or label them clearly
Multipacks and sizesCompare unit prices (per ounce, per count) for consumables

Step 5

Keep prices live

"Live" doesn't mean fetching every store on every page view. That's slow, and it gets you rate-limited. Use tiers:

  • Background refresh of every tracked offer, daily as a baseline.
  • Hot refresh of offers people are viewing or tracking, every few minutes to hours.
  • Just-in-time check of the winning offer before a click-out or a price-drop alert. If it changed, update the page before sending anyone.

Write every observation to a price history table with its timestamp. History powers price-drop alerts and "lowest in 30 days" claims, and it lets you spot extraction errors: a price that drops 90% overnight is usually a parsing bug, not a deal. Respect each store's robots rules and rate limits, and cache aggressively.

Step 6

A minimal architecture

  • Discovery: feeds, search or sitemaps produce candidate product URLs.
  • Fetch and extract: turn each URL into a normalized offer (price, currency, variant, stock).
  • Match: attach each offer to a canonical product, or mark it unmatched for review.
  • Store: canonical products, current offers, and price history.
  • Serve: for a product, rank in-stock offers for the same variant by price.
  • Refresh: the tiered loop above, plus alerts when extraction starts failing for a store.
schema.sql: the core tables
create table products (
  id          bigint primary key,
  gtin        char(14) unique,      -- null when no identifier is known
  brand       text not null,
  mpn         text,
  title       text not null
);

create table offers (
  product_id  bigint references products(id),
  store       text not null,
  url         text not null,
  variant     jsonb not null,       -- {"size": "M", "color": "black"}
  price       numeric(12, 2) not null,
  original    numeric(12, 2),
  currency    char(3) not null,
  in_stock    boolean,              -- null = unknown
  checked_at  timestamptz not null,
  primary key (product_id, store, variant)
);

create table price_history (
  product_id  bigint,
  store       text,
  variant     jsonb,
  price       numeric(12, 2),
  currency    char(3),
  observed_at timestamptz
);

Options

Where the live product data can come from

The hard part of a price comparison tool is the data: discovery, extraction, matching and freshness across many stores. These are the main ways to get it.

Data sources for a multi-store price comparison tool
OptionWhat it isGood atTrade-offsPricing
Build it yourselfYour own crawlers and per-site parsers, or a headless browser plus an LLM that fills your schema.Full control over fields, sources and refresh schedule.Every store is a parser to maintain. Anti-bot, rendering, matching and freshness are all yours.Engineering time, proxies, browsers and LLM tokens
FirecrawlScrapes any URL into Markdown, JSON shaped by a schema you pass, or a product object. Also searches the web.Any page on the open web, including stores no product index covers. The product format returns variants with price and availability without an LLM.One page per request. You supply the URLs, match the same product across stores, and schedule refreshes. Scrapes are cached for up to 2 days by default.1 credit per page; JSON mode adds 4
Zyte APIWeb data API: send a URL, get an AI-extracted product record, with ban handling and browser rendering built in.Dependable extraction at scale from sites you choose, including hard anti-bot targets.No cross-store product search. You bring the URLs, schedule refreshes, and match products yourself.Per successful response, priced by site difficulty
ApifyMarketplace of scraping Actors, including a general E-commerce Scraping Tool and many store-specific Actors.Configurable bulk collection, keyword search across marketplaces, and exports to JSON, CSV or Excel.You run and schedule Actors and store the datasets. Field names differ between Actors, so mapping them to one schema is yours.Pay per result, from $1 / 1k product details
DatafinitiProduct database that merges listings sharing an identifier (UPC, EAN, ASIN) into one record per product.Identifier-keyed records with price observations across merchants, bulk downloads for analytics, and an MCP server.One merged record per product rather than each store's current variants and stock. Queries use field filters, not plain language.Per record, from $99 / month for 5,000
Channel3Product search and URL lookup API for AI shopping, with an MCP server. Reports about 100M products.Agent product search with merchant offers and commission-earning purchase links out of the box.Answers from its own catalog, so check that it covers the retailers you need. Affiliate offers are part of the model.1,000 free credits / month, then about $0.007 per call
StoreRouterIndex of covered stores' catalogs behind search and parse, in one enriched schema. REST, SDKs and MCP.Cross-store search and normalized product detail (variants, per-size stock, GTIN where the store publishes it) without running crawlers.Answers best from covered stores. Other URLs can fall back to a shallower live parse, and onboarding a new store takes hours to days.$2 / 1k parse · $14 / 1k search; $5 free credit / month

How to choose

  • Identical branded goods from large retailers, earning commission: affiliate network feeds, with an extraction API to fill gaps, or Channel3 for search with commission-earning links.
  • A fixed list of stores on your own schedule: Zyte or Firecrawl to fetch and extract; you run discovery, matching and refresh.
  • Configurable collection from specific marketplaces: Apify Actors.
  • Price history and analytics across merchants by UPC: Datafiniti.
  • Searching many stores from a plain-language query, with current prices and per-variant stock in one schema: StoreRouter.

Prices and capabilities are from each vendor's public docs and pricing pages as of November 6, 2026. Side-by-side detail: StoreRouter comparisons.

StoreRouter

Where StoreRouter fits

StoreRouter covers discovery and normalized offers. search finds products across covered stores from a plain-language query, with optional price, brand and catalog filters. parse returns each offer in one schema: current and original price, currency, per-variant stock, and GTIN where the store publishes it. Your code keeps the matching rules, ranking, price history and interface.

Example
# 1. Find offers across covered storescurl -sS https://api.storerouter.ai/v1/products/search \  -H "Authorization: Bearer $STOREROUTER_API_KEY" \  -H "Content-Type: application/json" \  -d '{"q": "Stanley Quencher 40 oz tumbler", "limit": 20}'# 2. Read one offer in full: price, stock, identifierscurl -sS https://api.storerouter.ai/v1/products/parse \  -H "Authorization: Bearer $STOREROUTER_API_KEY" \  -H "Content-Type: application/json" \  -d '{"url": "<productUrl from step 1>"}'

StoreRouter returns one current price per product page, with stock per variant; when a store prices sizes differently, check the variant you are comparing. It returns merchant URLs, not affiliate links, and it does not keep price history for you. Coverage is not every store: check catalog coverage for the retailers you need.

FAQ

Frequently asked questions

How do price comparison sites get their data?

Most combine affiliate network product feeds (which also pay commission on click-outs), direct feeds from merchants, and crawling or extraction for stores without a feed. Some license data from product data providers. The hard parts are matching identical products across stores and keeping prices current.

Is there an API for comparing prices across stores?

There are APIs for each part. Extraction APIs such as Firecrawl and Zyte turn a product URL into structured data, including price. Product databases such as Datafiniti sell identifier-keyed records with price observations. Product search APIs such as StoreRouter and Channel3 search many stores at once and return normalized offers. You still own the matching and ranking rules that make it a comparison.

How do I know two listings are the same product?

Compare GTINs (UPC or EAN) first, normalized to 14 digits with the check digit validated. Without one, use brand plus manufacturer part number, then brand, model tokens and key attributes with a tuned similarity threshold. Match at the variant level, and label uncertain matches as similar rather than identical.

How often should prices be refreshed?

Daily for the whole catalog as a baseline, more often for products people are viewing or tracking, and a just-in-time check of the winning offer before a click-out or alert. Store each observation with a timestamp, and show when a price was last checked.

Is it legal to scrape prices from other stores?

Prices on public pages are generally treated as facts, but the rules depend on your jurisdiction, each site's terms, and how you collect the data. Respect robots.txt and rate limits, don't collect personal data, and get legal advice for a commercial product. Affiliate feeds and licensed data sources avoid most of the question.

Can an AI agent do price comparison?

Yes, if it has a tool that returns structured offers rather than raw web pages. Give it product search and product detail tools (through MCP or function calling), and have it compare the same variant across stores, check stock, and cite each price with the time it was checked.