How to Scrape Tesco Product Data with an API
Learn the lawful way to access Tesco product data: permission, API choices, runnable code, freshness controls, retries, and troubleshooting.
Direct answer: you should not automate access to Tesco’s website until you have Tesco’s prior written consent and a clear licence for the fields and downstream use you need. Tesco’s current UK general terms prohibit automated systems, including bots, crawlers, scrapers and AI tools, from accessing, extracting or collecting site data without prior written consent. The same terms restrict copying, distribution and commercial use of site content without written permission. See Tesco’s general terms.
No current, public Tesco grocery catalogue API documentation was established in the available research. A public wrapper records historical Tesco Labs product-search and product-detail endpoints, but that is a third-party, historical reference. Do not assume those endpoints still work, that Tesco supports them, or that they grant permission.
1. Choose an authorised access route
| Route | What it gives you | What you must confirm |
|---|---|---|
| Direct Tesco or partner access | Best source provenance and a contract with Tesco or its licensor | Current endpoint, credentials, fields, rate limits, geographic scope, storage, display, retention and redistribution rights |
| Third-party Tesco data API | A vendor-managed interface for product retrieval | Vendor’s lawful collection basis, coverage, field definitions, refresh interval, store context, error behaviour, retention and resale terms |
| Public-site scraping | Browser HTML or rendered pages | Written Tesco permission first; technical access alone is not authorisation |
Unwrangle documents a Tesco product-data endpoint at its Tesco API documentation. Upscrape documents a Tesco product-detail capability at its Tesco API documentation. These pages describe those vendors’ services; they do not prove Tesco authorised your use or that the returned data may be republished.
2. Get permission in writing before writing code
Ask Tesco or the data licensor to confirm each item below. Keep the approval with your project records.
- Which endpoint or approved provider you may use.
- Whether search, detail, reviews, nutrition, images, prices and availability are included.
- Which countries, stores, fulfilment areas and customer contexts are covered.
- Authentication method, request limits, concurrency limits and maintenance contacts.
- Whether you may store raw responses, normalised fields, images and historical prices.
- Whether you may display, compare, export or sell derived data.
- Required attribution, deletion procedures and retention period.
- Rules for personal data, Clubcard information, account data and delivery addresses.
Permission to call an endpoint does not automatically grant permission to copy, commercially use or redistribute everything it returns.
3. Design the data contract
Define a stable internal schema before ingesting records. A practical record can include:
{
"source": "tesco",
"source_product_id": "approved-source-id",
"barcode": "optional-barcode",
"name": "Product name",
"brand": "Brand",
"category": "Category",
"price_observed": 0.00,
"currency": "GBP",
"promotion": null,
"availability": "unknown",
"size": "500 g",
"ingredients": null,
"nutrition": null,
"country_of_origin": null,
"preparation_instructions": null,
"source_url": "https://www.tesco.com/...",
"observed_at": "2026-09-29T05:08:21Z",
"store_or_fulfilment_context": null,
"raw_response_hash": "sha256:..."
}
Tesco’s supplier material lists examples such as barcode, ingredients, nutrition, serving size, country of origin, preparation instructions, alcohol by volume and recyclable information. Treat these as possible supplier fields, not a promise that a public developer API returns all of them. Preserve the source product identifier and retrieval timestamp on every record.
4. Call the approved API
The examples below use placeholder values because the correct endpoint and authentication depend on your written agreement. Replace them only with the URL, headers and parameters supplied by Tesco or your authorised vendor.
cURL
curl --fail-with-body --retry 3 --retry-delay 2 \
--connect-timeout 10 --max-time 60 \
-H "Authorization: Bearer $API_TOKEN" \
-H "Accept: application/json" \
--get "$APPROVED_API_URL" \
--data-urlencode "product_id=$PRODUCT_ID" \
--data-urlencode "fields=id,name,barcode,price,availability,ingredients,nutrition"
Python
import os
import time
import requests
API_URL = os.environ["APPROVED_API_URL"]
TOKEN = os.environ["API_TOKEN"]
PRODUCT_ID = os.environ["PRODUCT_ID"]
params = {
"product_id": PRODUCT_ID,
"fields": "id,name,barcode,price,availability,ingredients,nutrition",
}
headers = {"Authorization": f"Bearer {TOKEN}", "Accept": "application/json"}
for attempt in range(4):
try:
response = requests.get(API_URL, params=params, headers=headers, timeout=(10, 60))
if response.status_code in (429, 500, 502, 503, 504):
if attempt == 3:
response.raise_for_status()
time.sleep(2 ** attempt)
continue
response.raise_for_status()
record = response.json()
print(record)
break
except requests.RequestException:
if attempt == 3:
raise
time.sleep(2 ** attempt)
Node.js
const apiUrl = process.env.APPROVED_API_URL;
const token = process.env.API_TOKEN;
const productId = process.env.PRODUCT_ID;
const url = new URL(apiUrl);
url.searchParams.set('product_id', productId);
url.searchParams.set('fields', 'id,name,barcode,price,availability,ingredients,nutrition');
for (let attempt = 0; attempt < 4; attempt++) {
const res = await fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
Accept: 'application/json'
}
});
if (![429, 500, 502, 503, 504].includes(res.status)) {
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
console.log(await res.json());
break;
}
if (attempt === 3) throw new Error(`HTTP ${res.status}`);
await new Promise(resolve => setTimeout(resolve, 2 ** attempt * 1000));
}
5. Normalise, validate and store safely
- Validate required identifiers and reject records with no approved source ID.
- Parse prices as decimal values, never binary floating point, and store the currency.
- Keep unknown, missing and unavailable distinct; do not turn a missing value into zero.
- Store
observed_at, source URL and store or fulfilment context when supplied. - Hash or version raw responses so a field change can be audited without duplicating every payload.
- Encrypt credentials in a secret manager. Never place keys in browser code, Git, logs or error messages.
- Apply the approved retention and deletion rules to raw and derived data.
6. Handle price, stock and product changes
Tesco’s grocery terms say online prices are guide prices and that the final amount can differ when an order is picked. A captured price is therefore a timestamped observation, not a guaranteed checkout price. The terms also describe product details changing as stock is refreshed, including examples such as alcohol by volume or vintage. Link each value to its retrieval time and avoid language such as “live price” unless your agreement and system genuinely provide that guarantee. See the grocery product terms.
| Situation | Recommended handling |
|---|---|
| Price changed | Insert a new observation; retain the prior value and timestamp. |
| Product unavailable | Keep the product ID, set availability explicitly and do not delete history automatically. |
| Pack size changed | Compare size and barcode before treating records as the same product. |
| Store-specific result | Store the store, postcode or fulfilment context allowed by the agreement. |
| Field disappears | Record a schema warning and preserve the previous value with its old timestamp. |
7. Pagination, rate limits and reliability
- Use the provider’s documented cursor or page token; never guess undocumented parameters.
- Respect the lower of your contract limit and the provider’s published limit.
- Retry timeouts, 429 and transient 5xx responses with exponential backoff and jitter.
- Do not retry authentication failures, validation errors or permission denials without fixing the request.
- Use idempotency keys if the provider supports them, especially for asynchronous jobs.
- Persist progress after each page so a restart does not repeat the entire catalogue.
- Monitor success rate, latency, response age, missing-field rate and duplicate IDs.
- Keep a dead-letter queue for records that fail validation, with the response status and request correlation ID.
8. Performance and cost planning
Estimate volume as products × refreshes per product × requested fields. Request only fields you are licensed to use and need. Detail calls are usually more expensive than a permitted search or bulk operation, so cache unchanged records according to your agreement. Separate a fast-changing price or availability refresh from a slower nutrition and ingredients refresh. Measure vendor billing units, retries and failed calls before committing to a budget; the research does not provide comparable benchmarks or prices for the vendors.
9. Common errors and fixes
| Error | Likely cause | Fix |
|---|---|---|
| 401 or 403 | Wrong key, expired credential, missing scope or unauthorised endpoint | Verify the approved URL and credential scope with the provider; do not rotate through keys or bypass access controls. |
| 404 | Product ID, URL or historical endpoint no longer exists | Confirm the identifier format and current documentation. Treat historical Tesco Labs paths as unverified. |
| 429 | Rate or concurrency limit exceeded | Reduce concurrency, honour Retry-After, add backoff and request a documented limit increase. |
| 5xx or timeout | Provider or upstream transient failure | Retry a bounded number of times, then queue the record for later and alert on sustained failure. |
| Empty or partial JSON | Unavailable product, location context, field restriction or schema change | Log the raw status, validate fields, and ask the provider which context and fields are supported. |
| Price does not match checkout | Guide price, picking-time change, substitution or store context | Label it as an observed price with timestamp and context; do not promise final checkout pricing. |
| Blocked browser or CAPTCHA | Unauthorised direct-site automation or anti-bot control | Stop the automated access and obtain written permission or use an authorised data provider. |
10. When a browser is genuinely required
If your written agreement explicitly permits rendered-page capture, use a controlled browser only for the approved pages and fields. Record consent scope, throttle requests, avoid login and personal data unless expressly covered, and keep screenshots or HTML only for the permitted retention period. Do not inspect network calls to discover undocumented Tesco endpoints and treat a working request as proof of permission.
Or skip the browser setup
If you need a visual record of an approved Tesco product page, ScreenshotNeo can return a screenshot or PDF from one GET request. Its consent step accepts cookie banners and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; bot checks, blank pages, failed loads and cache hits are not billed, and the response identifies the verdict and billing status. An MCP server provides take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.
See the ScreenshotNeo API documentation. Example:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://www.tesco.com/groceries/en-GB/products/256092964 -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://www.tesco.com/groceries/en-GB/products/256092964"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://www.tesco.com/groceries/en-GB/products/256092964' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
FAQ
Does Tesco have a public product API?
The research did not establish current public documentation for a general Tesco grocery catalogue API. Ask Tesco or an authorised partner for the current route and terms.
Can I use an old Tesco Labs endpoint I found on GitHub?
Only after independently confirming that Tesco currently supports it and has authorised your intended use. A historical wrapper proves that code existed, not that the endpoint is available or permitted today.
Can I publish Tesco prices in my comparison site?
Only if your written agreement covers storage, display, comparison and redistribution. Also show retrieval time and context because online prices can be guide prices.
Which fields should I refresh most often?
Refresh price and availability according to the permitted service limits and your product needs. Refresh slower-changing fields such as ingredients or nutrition separately, and retain timestamps for both.


