logo

Google Shopping Product API

View as Markdown

Fetch the full product page (sellers, variants, specs, reviews, videos) for a single Google Shopping product as structured JSON

The Google Shopping Product API is the companion endpoint to /plugin/google/shopping. It fetches the full product page for a single Google Shopping product — every seller offer, variants, specs, reviews, videos, and related discussions — as structured JSON.

The recommended flow is three steps: call /plugin/google/shopping to find a product, capture its catalog_id, hit this endpoint to get the product page with its first sellers, then replay the next_page_token against /plugin/google/shopping/product/stores to walk the rest of the seller list. Add gpcid when you need every offer from the specific cluster opened by a Google Shopping result card instead of the catalog-wide seller list.

Credit Usage: Each successful request costs 10 credits. For bulk processing, use the Async API with plugins.

Identifier choice: catalog_id is the durable input — persist it in your DB and replay it weeks or months later. You can optionally pair it with the product query (q) or an offer-cluster ID (gpcid). immersive_product_page_token is short-lived (a few hours) and best used inside the same workflow that produced it. product_id always works but returns a lean response without variants / specs / reviews.

Catalog IDs are region-specific. Google maintains a separate catalog graph per market, so the same product has a different catalog_id in each region. If you need US, DE, and FR sellers for the same product, run /plugin/google/shopping once per region (passing gl=us / gl=de / gl=fr) and persist the catalog_id you receive in each market.

Key Features

  • Durable Catalog Input: Pass catalog_id to look up a product by its long-lived Google catalog identifier. Catalog IDs are stable per region, so you can save them in your own storage and replay them later.
  • Offer Cluster Targeting: Add the gpcid from a Google Shopping product link to return every seller shown on that result card's cluster page without mixing in offers from other clusters.
  • Rich Product Data: Title, gallery, brand, rating, ratings histogram, thumbnails, variants, specs, videos, customer review images, top insights, related discussions — all parsed into structured fields.
  • Large Seller Lists: The default catalog page returns the headline ~5 sellers and a continuation token (next_page_token). Replay it against /plugin/google/shopping/product/stores to walk up to ~1,000 sellers. Pass load_all_stores=true to have the gateway walk the first ~100 sellers for you in a single request.
  • Variant Filtering: In token mode, pass pvf to narrow stores[] to one variant's offers (a colour, a size, a storage capacity) instead of the union of every variant's offers. See Variant filter.
  • Per-seller Detail: Price, shipping, tax, total, payment methods, delivery / returns details, merchant ID, thumbnail, badge text, sale & strikethrough prices, and carrier-style monthly installment plans (installment_months, installment_down_now, total) when applicable.
  • Three Response Modes: catalog_oapv (catalog mode, recommended), oapv (token mode, rich short-lived payload), and html (legacy product-id-only fallback). The chosen mode is echoed in product_results.source.
  • Worldwide Coverage: Locale via gl + hl + location / uule; carrier financing and EU comma-decimal formatting handled automatically.
  • Device Emulation: Desktop, mobile, or tablet layout with the device parameter.
  • No Blocks or CAPTCHAs: All anti-bot measures are handled automatically by Scrape.do.

Endpoint

GET https://api.scrape.do/plugin/google/shopping/product

Parameter keys are case-insensitive. You can use product_id, Product_ID, gl, GL, etc.


Request Parameters

Required

ParameterTypeDescription
tokenstringYour Scrape.do API authentication token

Identity (choose one)

Provide one of the identifiers below. When you supply more than one, the priority is catalog_id > immersive_product_page_token > product_id.

InputTypeDescription
catalog_idstringRecommended. Durable catalog identifier (digit-only) from /plugin/google/shopping or the catalogid: value in a Google Shopping link's prds parameter. Returns the catalog response (source: "catalog_oapv"): full product page + the first ~5 sellers + a next_page_token when more sellers remain. q and gpcid are optional. For catalogs with multiple variants, every seller page stays on the variant Google selected for that catalog_id.
immersive_product_page_tokenstringShort-lived opaque base64 token from a shopping_results[] entry on /plugin/google/shopping. Returns the rich token response (source: "oapv"): variants, specs, reviews, videos, full seller list. Without a variant filter, seller offers can span multiple variants. Best used inside the same workflow that produced it. The only path that supports the pvf variant filter.
page_tokenstringAlias for immersive_product_page_token. Behaves identically.
product_idstringGoogle product catalog ID (digit-only). Returns the HTML fallback (source: "html"): title, product_id, sellers. Required when you want sort_by.

Offer cluster

ParameterTypeDefaultDescription
qstring—Catalog mode only. Optional search query for the product, such as its title. When omitted, the product page opens with a blank query, matching Google's own product links.
gpcidstring—Catalog mode only. Digit-only offer-cluster ID from the gpcid: value in a Google Shopping link's prds parameter. Requires catalog_id and cannot be combined with sort_by.

Google can divide one catalog into multiple offer clusters. A link containing only prds=catalogid:11098835974841238015 opens the catalog-wide product page. A link containing prds=catalogid:11098835974841238015,gpcid:3719569561376036875,… opens one cluster, which can have a different title and seller list.

Pass catalog_id alone for catalog-wide price comparison. Add gpcid when you need every seller shown on the specific cluster page opened by a result card. A cluster response usually contains 1–5 offers, does not include next_page_token, and is not expanded by load_all_stores=true, so sellers from other clusters are never mixed into the result.

Do not send next_page_token to this endpoint. Continuation cursors go to /plugin/google/shopping/product/stores. Sending one here returns HTTP 400 with a redirect message.

Device

ParameterTypeDefaultDescription
devicestringdesktopDevice type. One of desktop, mobile, tablet.

Routing

ParameterTypeDefaultDescription
google_domainstringgoogle.comGoogle domain to query (e.g., google.de, google.com.tr).

Sort

ParameterTypeDefaultDescription
sort_bystring—Seller sort order on the HTML fallback path. One of base_price, total_price, promotion, seller_rating.

sort_by is only honored on the HTML fallback path. Passing it alongside immersive_product_page_token forces fallback and you lose variants, specs, reviews, and videos. To re-sort sellers without losing the rich payload, sort stores[] client-side by extracted_total or extracted_price.

Variant filter

ParameterTypeDefaultDescription
pvfstring—Token mode only. Narrows the seller list to a single product variant — a colour, a size, a storage capacity. Take the value from product_results.variants[].options[].pvf on a previous call to this endpoint.

Without pvf, stores[] is the union of every variant's offers — the same list Google shows before you pick a swatch. A product sold in three colours and three capacities returns offers mixing all nine combinations, so a price comparison across them is not like-for-like.

Filtering takes two calls:

  1. Call the endpoint with no pvf and read product_results.variants[]. Every option you can switch to carries the pvf value that selects it; the option already selected and the "Any" option (such as Any Color) have none.
  2. Call the endpoint again with that value as pvf. stores[] now contains only offers for that variant, and variants[].options[].selected flags the option you applied.

selected appears only on the option currently applied on that variant axis — it previously came back on every option, so code that filtered on it used to match the whole list.

pvf values are durable — the product token is not. A pvf encodes the variant, not your session, so you can store one and reuse it later. Every call still needs a freshly minted immersive_product_page_token, so replay a stored pvf against a new token. Only values returned in a response are accepted: a hand-built one is rejected with 400, because the attribute names inside it follow the page language (colour on gl=ca, color on gl=us) and a guessed name would quietly return an unfiltered list.

product_results.applied_pvf echoes the filter Google actually applied. It is absent when you sent no pvf — so if you did send one and applied_pvf is missing, the filter did not take effect and stores[] is unfiltered.

pvf combines with more_stores, which widens the seller window from ~5 to ~10. A filtered list does not paginate beyond that — no next_page_token is returned on a pvf-filtered response, because a continuation cursor cannot carry the filter and would page you back into unfiltered results. It does not combine with sort_by, product_id, or catalog_id: those select modes that cannot filter, so they return 400 rather than silently ignoring the filter.

Seller list expansion

ParameterTypeDefaultDescription
load_all_storesbooleanfalseCatalog mode only; no effect with gpcid. When true, the gateway walks the continuation cursor internally and returns every seller it reaches in one response. The walk is hard-capped (default ~10 pages, ~100 sellers). A capped or partially failed walk returns the sellers collected so far, a next_page_token for manual continuation, and the Scrape.do-Auto-Page-Truncated: true response header. A walk that fails before collecting any sellers returns HTTP 502. Each additional upstream hop counts toward the request's credit cost.
more_storesbooleanfalseToken mode only (legacy). When true, asks the legacy token flow to expand the seller list inline. Catalog mode uses next_page_token + /plugin/google/shopping/product/stores instead.

Cursor opacity: next_page_token is an opaque, signed string the gateway emits in the response. Replay it verbatim against /plugin/google/shopping/product/stores — do not parse, transform, or generate cursors yourself. The cursor is omitted when the seller list is exhausted, on gpcid responses, and when continuation reaches its ~1,000-seller safety limit. At the safety limit, Scrape.do-Auto-Page-Truncated: true distinguishes truncation from the natural end of the list.

Localization

ParameterTypeDefaultDescription
hlstringenHost language. Overrides the language embedded in immersive_product_page_token when both are present.
glstringusCountry perspective. Overrides the country embedded in immersive_product_page_token when both are present. One exception on the token (seller-list) path: the upstream session the token replays into is region-bound, so a gl that would move the request to a different market than the token was minted in yields to the token's country there. A gl from the same market as the token is still honored, and the hl language is unaffected.
locationstring—Location name (e.g., Austin,Texas,United States). Auto-encoded to UULE when uule is not set.
uulestring—Google-encoded location parameter. Overrides location when both are set.

See Localization for the full list of supported hl, gl, and google_domain values.


Example Usage

# 1. Look up the product and grab its catalog_id
CID=$(curl -s "https://api.scrape.do/plugin/google/shopping?q=PodTrak+P8+ZP8&hl=en&gl=us&token=YOUR_TOKEN" \
  | jq -r '.shopping_results[0].catalog_id')

# 2. Fetch the product page + first sellers + continuation token
curl "https://api.scrape.do/plugin/google/shopping/product?catalog_id=$CID&q=PodTrak+P8+ZP8&hl=en&gl=us&token=YOUR_TOKEN"

q is optional. If you already have a Google Shopping product link, you can call the endpoint with its catalogid: value alone:

curl "https://api.scrape.do/plugin/google/shopping/product?catalog_id=11098835974841238015&gl=us&token=YOUR_TOKEN"

By offer cluster

Use the catalogid: and gpcid: values from the same product link to return all offers on that cluster page:

curl "https://api.scrape.do/plugin/google/shopping/product?catalog_id=11098835974841238015&gpcid=3719569561376036875&gl=us&token=YOUR_TOKEN"

Catalog mode in another market

# Same product, German market — re-search per region to get the region-scoped catalog_id
CID=$(curl -s "https://api.scrape.do/plugin/google/shopping?q=iPhone+17+Pro&hl=de&gl=de&token=YOUR_TOKEN" \
  | jq -r '.shopping_results[0].catalog_id')

curl "https://api.scrape.do/plugin/google/shopping/product?catalog_id=$CID&q=iPhone+17+Pro&hl=de&gl=de&token=YOUR_TOKEN"

Load the first ~100 sellers in one call

curl "https://api.scrape.do/plugin/google/shopping/product?catalog_id=$CID&q=PodTrak+P8+ZP8&load_all_stores=true&token=YOUR_TOKEN"

By immersive_product_page_token (rich short-lived response)

# 1. Mint a token from the search endpoint
TOKEN=$(curl -s "https://api.scrape.do/plugin/google/shopping?q=Sony+WH-1000XM5&token=YOUR_TOKEN" \
  | jq -r '.shopping_results[0].immersive_product_page_token')

# 2. Replay it against the product endpoint (variants/specs/reviews/videos returned)
curl "https://api.scrape.do/plugin/google/shopping/product?immersive_product_page_token=$TOKEN&token=YOUR_TOKEN"

Filter by variant (pvf, token mode)

# 1. Mint a token from the search endpoint
TOKEN=$(curl -s "https://api.scrape.do/plugin/google/shopping?q=Sony+WH-1000XM5&token=YOUR_TOKEN" \
  | jq -r '.shopping_results[0].immersive_product_page_token')

# 2. Fetch the product with no filter and read the options.
#    stores[] mixes every variant; each option carries the pvf that selects it.
curl "https://api.scrape.do/plugin/google/shopping/product?immersive_product_page_token=$TOKEN&token=YOUR_TOKEN"

# 3. Call again with the pvf of the option you want.
curl "https://api.scrape.do/plugin/google/shopping/product?immersive_product_page_token=$TOKEN&pvf=Eg8iBWNvbG9yKgZzaWx2ZXI&token=YOUR_TOKEN"
# → every row in stores[] is an offer for that variant, and applied_pvf echoes the filter

By product_id (HTML fallback)

curl "https://api.scrape.do/plugin/google/shopping/product?product_id=7000474567848623813&token=YOUR_TOKEN"

Response

Top-Level Structure

{
  "search_parameters": { ... },
  "product_results":   { ... }
}

search_parameters

Echo of the request parameters sent by the client.

{
  "engine": "google_shopping_product",
  "product_id": "7000474567848623813",
  "page_token": "eyJlaSI6ImFhX1Nh...",
  "google_domain": "google.com",
  "hl": "en",
  "gl": "us",
  "device": "desktop",
  "more_stores": false,
  "next_page_token": ""
}

Optional fields appear only when sent: gpcid, location, uule, and sort_by. Catalog mode always echoes catalog_id, q (empty when you omit it), and load_all_stores.

product_results (rich path)

Returned when you pass immersive_product_page_token and do not pass sort_by. source is "oapv".

{
  "title": "Sony WH-1000XM5 Wireless Noise Canceling Headphones",
  "product_id": "7000474567848623813",
  "brand": "Sony",
  "rating": 4.6,
  "reviews": 4800,
  "reviews_label": "4,800 reviews",
  "ratings": [
    { "stars": 5, "count": 3400 },
    { "stars": 4, "count": 900 }
  ],
  "thumbnails": [ "https://encrypted-tbn0.gstatic.com/...", "..." ],
  "reviews_images": [ "https://encrypted-tbn0.gstatic.com/...", "..." ],
  "stores": [ { /* see stores[] table below */ } ],
  "next_page_token": "eyJzb3JpIjo1LCJtbm8iOjEwfQ",
  "variants": [ { "type": "Color", "options": [ { "text": "Any Color" }, { "text": "Black", "selected": true }, { "text": "Silver", "pvf": "Eg8iBWNvbG9yKgZzaWx2ZXI", "shoprs": "Eg8iBWNvbG9yKgZzaWx2ZXI" } ] } ],
  "specs": [ { "section": "General", "items": [ { "label": "Wireless", "value": "Yes" } ] } ],
  "videos": [ { "title": "Sony WH-1000XM5 Review", "source": "youtube.com", "thumbnail": "...", "link": "..." } ],
  "user_reviews": [ { "rating": 5, "title": "Best headphones", "body": "...", "author": "John D." } ],
  "top_insights": [ { "section": "Sound quality", "items": [ "Crystal-clear audio", "Strong bass" ] } ],
  "about_the_product": { "description": "..." },
  "more_options": [ { "title": "Sony WH-1000XM4", "link": "...", "thumbnail": "..." } ],
  "discussions_and_forums": [ { "title": "...", "source": "reddit.com", "link": "...", "snippet": "..." } ],
  "extension_ids": { "catalog_id": "...", "gpcid": "..." },
  "source": "oapv"
}

product_results (HTML fallback)

Returned when you pass only product_id, or when you pass sort_by alongside the token. source is "html". Lean shape — no variants, specs, videos, or reviews — but the seller list works.

{
  "title": "Sony WH-1000XM5 Wireless Noise Canceling Headphones",
  "product_id": "7000474567848623813",
  "stores": [ { /* see stores[] table below */ } ],
  "source": "html"
}

stores[] Fields

Each entry in product_results.stores[] describes a single merchant offer for the product.

FieldTypeAlways presentDescription
positionintyes1-based position in the seller list
namestringyesMerchant name (e.g., "Best Buy", "Amazon.com")
logostringMerchant favicon URL
linkstringDirect link to the merchant's product page. Google /goto redirects are resolved before the URL is returned.
titlestringProduct title as listed on the merchant's site (may differ slightly from product_results.title). Available in rich and catalog responses.
ratingfloatMerchant rating out of 5
reviewsfloatMerchant review count (suffix-aware, e.g., 1.2K is parsed as 1200)
pricestringFormatted base price ("$248.00", "1.299,00 TL")
extracted_pricefloatNumeric base price
currencystringISO currency code when detected ("USD", "EUR", "TRY")
shippingstringShipping line as displayed ("+ 7,99 €", "Lieferung: 6,95 €", "Free delivery")
shipping_extractedfloatNumeric shipping cost. Omitted when delivery is free or the shipping line has no amount.
taxstringFormatted tax line when shown
extracted_taxfloatNumeric tax value
tax_hintstringTax hint shown by Google when an exact tax line isn't available (e.g., "+tax")
totalstringFormatted total (price + shipping + tax)
extracted_totalfloatNumeric total
payment_methodsstringAccepted payment methods (e.g., "PayPal, Affirm accepted")
details_and_offersstring[]Per-offer notes — delivery window, stock, return policy (e.g., ["Free delivery between May 21 – 27", "In stock", "90-day returns"])
merchant_idstringGoogle's internal merchant ID. Available in rich responses, US catalog leading rows, and catalog continuation rows; Google does not expose it on EU catalog leading rows.
thumbnailstringMerchant-specific product thumbnail when distinct from the canonical image
tagstringBadge text Google renders on the offer, in the page locale (e.g. "Best price", "Bester Preis", "Meilleur prix"). Text is carried verbatim, not normalized.
original_pricestringPre-discount price as displayed, when Google renders a strikethrough
extracted_original_pricefloatNumeric pre-discount price
discountstringDiscount badge text (e.g., "20% OFF")
installment_monthsintNumber of monthly installments for carrier-style or BNPL offers (Verizon, AT&T, T-Mobile, congstar, MediaMarkt mit Vertrag, …). When set, price is the monthly figure, not the lump sum — read total / extracted_total for the lifetime cost.
installment_down_nowstringUpfront payment for the installment plan, as displayed (e.g., "$0", "60 €").

In catalog mode, the first 3–5 stores[] entries come from the product page and include the merchant name, link, title, price, shipping, rating, and tag, plus sale and installment fields when shown. Sellers added through load_all_stores=true or /plugin/google/shopping/product/stores come from Google's continuation feed and can also include currency, total, details_and_offers, logo, and thumbnail.


Three Response Modes

The plugin picks the response mode automatically based on what you sent:

You sentModesourceWhat you get
catalog_id with optional q or gpcid (no sort_by)Catalog"catalog_oapv"Full product page (title, gallery, description, ratings) + the first ~5 sellers. Catalog-wide requests include next_page_token when more sellers exist; gpcid requests return only that cluster and do not paginate. Catalog-wide pages stay on the same Google-selected variant.
immersive_product_page_token (no sort_by)Token"oapv"Full payload — variants, specs, reviews, videos, all sellers
product_id onlyHTML fallback"html"Title, product_id, sellers
Any input and sort_byHTML fallback"html"Sorted sellers, no variants / specs / reviews / videos

Inspect product_results.source to know which mode served the response. Catalog mode is the recommended default for any workflow that persists product identifiers.

The pvf variant filter is supported in token mode only — sending it with catalog_id, product_id, or sort_by returns HTTP 400.


Paginating every seller

Catalog mode without gpcid returns up to ~5 sellers inline plus a next_page_token when more remain. For catalogs that group multiple sizes, finishes, colors, or other variants, the first response and every continuation page stay on the variant Google selected for that catalog_id. If Google cannot provide a variant-pinned view, the endpoint returns the first seller page without a next_page_token rather than continuing with offers from other variants. Use catalog pagination in one of two ways:

Option 1 — Manual pagination via /plugin/google/shopping/product/stores

The dedicated continuation endpoint accepts the signed token and returns the next batch of sellers (up to ~10 per call). It's the most cost-efficient path because each call is a single hop when the embedded session is still fresh.

GET https://api.scrape.do/plugin/google/shopping/product/stores
ParameterTypeDescription
tokenstringYour Scrape.do API authentication token
catalog_idstringThe same catalog_id you used on the matching /plugin/google/shopping/product call. Must match the catalog_id embedded inside next_page_token.
next_page_tokenstringThe next_page_token value from a prior response. Replay verbatim. The locale (q, gl, hl) is carried inside the token and reused server-side — you do not pass them again.
# After the catalog call:
NEXT=$(echo "$RESP" | jq -r '.product_results.next_page_token // empty')

while [ -n "$NEXT" ]; do
  RESP=$(curl -s "https://api.scrape.do/plugin/google/shopping/product/stores?catalog_id=$CID&next_page_token=$NEXT&token=YOUR_TOKEN")
  echo "$RESP" | jq '.product_results.stores | length'
  NEXT=$(echo "$RESP" | jq -r '.product_results.next_page_token // empty')
done

Response shape is lean — only product_id, stores[], and (when more sellers remain) next_page_token. Title, gallery, variants, etc. are not re-emitted; you already have them from the catalog call. source is "catalog_oapv_more".

The token is signed and bound to the supplied catalog_id. Sending a different catalog_id returns HTTP 400 ("catalog_id mismatch").

Each continuation call returns up to ~10 sellers, and pagination can continue to roughly 1,000 sellers. A short final page has no next_page_token. If a full page reaches the safety limit instead, it also omits next_page_token but includes Scrape.do-Auto-Page-Truncated: true, so you can distinguish truncation from the natural end of the list.

Google can repeat a seller on later pages in long result sets. When combining pages, de-duplicate offers by merchant_id.

Option 2 — One-shot load_all_stores=true

For workflows that want a larger seller batch in a single response, pass load_all_stores=true on the catalog call. The gateway walks the continuation cursor for you and returns the merged seller list. The walk is billed per upstream hop and capped at about 10 pages (~100 sellers) by default. If the cap is reached or a later page fails, the response keeps the sellers collected so far and includes a next_page_token for manual continuation plus the Scrape.do-Auto-Page-Truncated: true response header. If the walk fails before collecting any sellers, the endpoint returns HTTP 502 and the request is not charged.

curl "https://api.scrape.do/plugin/google/shopping/product?catalog_id=$CID&q=iPhone+17+Pro&load_all_stores=true&token=YOUR_TOKEN"

Legacy more_stores on the token path

The legacy token flow (immersive_product_page_token) uses more_stores=true to inline the expanded seller list. New integrations should prefer the catalog path; more_stores stays available for existing callers.


Handling Session Expiry

immersive_product_page_token values are tied to an upstream Google session that ages out after several hours. When that happens, the plugin returns HTTP 410 Gone:

{
  "error": "session expired",
  "message": "The immersive_product_page_token is older than 6h0m0s and is past Google's product-viewer session lifetime. Fetch /plugin/google/shopping again to mint a fresh token, then retry."
}

(The exact lifetime message may vary; the recovery is always the same.)

Recovery: When you receive HTTP 410 on /plugin/google/shopping/product, re-fetch /plugin/google/shopping with the same query, grab a fresh immersive_product_page_token from the response, then retry the product call with the new token. Don't store tokens long-term — treat them as ephemeral cursors.

See Transient Errors for the full rotate-on-expiry pattern.


Error Handling

All endpoints return errors in a consistent JSON format:

{
  "error": "error_code",
  "message": "Human readable error message"
}

Common Error Codes

StatusErrorDescription
400token is requiredMissing authentication token
400gpcid requires catalog_idgpcid was sent without catalog_id
400gpcid is not supported with sort_bygpcid was combined with sort_by, which selects a mode that cannot target an offer cluster
400invalid gpcidgpcid was too long or contained non-digit characters
400invalid catalog_idcatalog_id was empty, too long, or contained non-digit characters
400next_page_token belongs on /plugin/google/shopping/product/storesA pagination cursor was sent to /product — replay it against /product/stores instead
400catalog_id mismatchOn /product/stores, the supplied catalog_id does not match the catalog_id embedded inside next_page_token
400product_id (or immersive_product_page_token) is requiredNo identifier was supplied at all
400invalid immersive_product_page_tokenToken could not be base64-decoded or its JSON payload could not be parsed
400invalid product_idproduct_id was empty, too long, or contained non-digit characters
400device must be one of: desktop, mobile, tabletInvalid device value
400invalid google_domainDomain not in the supported list
400invalid sort_bySort value not in base_price, total_price, promotion, seller_rating
400invalid pvfpvf was not a value returned in product_results.variants[].options[].pvf — only values a previous response returned are accepted
400pvf requires an immersive_product_page_tokenpvf was sent with product_id or sort_by, which select modes that cannot filter
400pvf is not supported with catalog_idpvf was sent with catalog_id — mint an immersive_product_page_token instead
400invalid next_page_tokenThe pagination cursor's signature failed, payload couldn't be parsed, a bounded field fell out of range, or the token belongs to a non-paginated gpcid request. Fetch a fresh first page from /plugin/google/shopping/product and resume from its cursor
410session expiredToken is past its upstream session lifetime. Re-mint via /plugin/google/shopping (token path) or simply retry the same request (catalog path — the server re-mints transparently and continues). See Handling Session Expiry below
502request failedTransient upstream failure. Retry
502unexpected responseNon-200 response from Google
502failed to load sellersload_all_stores=true failed before collecting any sellers. Retry the request
500failed to parse product viewer responseGoogle returned an unparseable product viewer payload (rare; if persistent, report to support)
500decompression failedResponse body decompression error

An empty seller list means no sellers are available in that market. When a catalog_id is valid in Google's index but the regional catalog graph has no sellers for it (common for US-specific catalogs queried with gl=de / gl=fr etc.), the response is 200 with product_results.stores = []. Re-search in the target region (/plugin/google/shopping?gl=de…) to get its region-specific catalog ID. A failed load_all_stores=true walk does not return an ambiguous empty response: it returns HTTP 502 when no sellers were collected, or a partial HTTP 200 response with Scrape.do-Auto-Page-Truncated: true when earlier pages succeeded.


On this page