Skip to content
test sites

Point your scraper here and check its homework.

Every test on this site has an answer key: a JSON file that lists exactly what a correct scraper should come back with. Run Netweir, Scrapy, Playwright, Crawlee, Firecrawl or something you wrote last night, then diff your output against the key. No guessing whether "about 500 products" was right.

The data is fixed. It comes from a seeded generator, so the catalogue you scrape today is the one you'll scrape next month, until the data version changes. You're on 1.0.0; it's in every answer key and at the foot of every page.

Bots are welcome. There are no challenges, no CAPTCHAs, no fingerprinting. The one thing standing between you and the site is a generous abuse limit at the edge, set well above anything a test needs. Keep to the published rules and you'll never meet it.tests.json lists every test for your harness.

Shop & pagination

Plain HTML, nothing clever, and still the place most scrapers lose records: pages they never reach, products they count twice.

TestWhat it testsDifficultyNeedsAnswer key
The catalogueCategories, subcategories, numbered pages and next links, full product pages with JSON-LD, and the traps real shops set: tracking parameters, missing trailing slashes, products listed twice, items out of stock.MediumHTTP onlyJSON

JavaScript pages

The data isn't in the HTML. Fetch these pages without a browser and you get an empty shell, which is the honest result.

TestWhat it testsDifficultyNeedsAnswer key
Infinite scrollNinety-six items arrive twelve at a time as you scroll. Stop scrolling early and you miss some.MediumNeeds JSJSON
Load more buttonSixty items behind a button that has to be clicked five times, waiting each time for the new rows.MediumNeeds JSJSON
Data from a JSON APIAn empty table the page fills from a JSON request after load. Render it, or find the API.EasyNeeds JSJSON
Shadow DOMReviews inside an open shadow root. document.querySelector can't see them; your selectors have to pierce it.HardNeeds JSJSON
Same-origin iframeA store list that lives in an iframe, rendered by script inside the frame.MediumNeeds JSJSON
Client-rendered appA single-page app that changes the URL with pushState. Every item has its own address, and none of them exists as HTML.HardNeeds JSJSON
Lazy-loaded imagesForty pictures that show a placeholder until they scroll into view. The real address only appears then.MediumNeeds JSJSON

Bad days

What the web does to a crawl at 3 a.m.: limits, delays, errors that clear on retry, redirects that never end, and a redesign overnight.

TestWhat it testsDifficultyNeedsAnswer key
Rate limitTwenty-one pages that answer 429 with Retry-After once you pass twelve requests in a ten-second window.MediumHTTP onlyJSON
Slow pagesPages that take one, three and ten seconds to answer. A short timeout loses the slow one.EasyHTTP onlyJSON
Pages that fail onceEvery fourth item answers 503 the first time you ask, then works. One page always fails.MediumHTTP onlyJSON
RedirectsA 301, 302, 307, 308 chain, a loop that never ends, and a meta refresh.EasyHTTP onlyJSON
Soft 404sTen product links. Three answer 200 but say the product is gone; one is a real 404.MediumHTTP onlyJSON
Redesign switchThe same fifty products in two layouts with every class renamed, plus a crossed-out price and a shipping charge to lure the wrong number.HardHTTP onlyJSON

Forms & logins

Cookies, tokens and state. No database behind any of it; every session is a signed cookie.

TestWhat it testsDifficultyNeedsAnswer key
Login and members areaLog in with the credentials on the page, keep the session cookie, and read three members-only pages that bounce you to the login without it.MediumNeeds cookiesJSON
CSRF tokenA form whose hidden token must come back with the cookie it was issued with. Replay it wrong and you get a 403.MediumNeeds cookiesJSON
Search formA GET search with paged results. Build the query string and follow the pages.EasyHTTP onlyJSON
Multi-step formThree steps, each a POST, carrying state in a signed cookie, ending in a reference code you can check.HardNeeds cookiesJSON

Manners

One check that has nothing to do with extraction.

TestWhat it testsDifficultyNeedsAnswer key
robots.txtA linked area that robots.txt disallows. A polite scraper fetches none of it.EasyHTTP onlyJSON