Developer & Web Scraping Sandbox
TestingURL.dev is a free web scraping test site and developer sandbox. Practice pages for crawlers and HTTP clients, from an ecommerce catalog to pagination, forms, and login walls.
Go ahead and scrape this site. Every page below has a known structure, robots.txt allows every path, and there's no rate limiting except on the one page built to demonstrate it. Nothing here is randomized between requests unless the page description says so.
Web Scraping
A web scraping test site with known, predictable markup. Practice pages for crawlers, scrapers, and browser automation, from a full ecommerce catalog to pagination, forms, and login walls.
Ecommerce catalog
A fake ecommerce store to scrape: category listings down to individual product detail pages, the classic web-scraping example.
- easy Store home — Browse every product category in the fake store.
- easy Category listing — Products within one category, each linking to its own detail page.
- easy Product detail page — A realistic ecommerce scraping target, with price, rating, stock, and related items.
Structured data & metadata
Machine-readable product, collection, and business data in the formats real sites use: JSON-LD, Microdata, Open Graph, and JS dataLayers.
- easy Format overview — The same demo product in every format below, for comparing extraction results.
- easy Product — JSON-LD — Product data exposed only via a schema.org/Product JSON-LD script.
- easy Product — Microdata — Same product, marked up with schema.org Microdata (itemscope/itemprop) instead of JSON-LD.
- easy Product — Open Graph — Same product, exposed only via Open Graph / product: meta tags in <head>.
- medium Product — dataLayer — Same product pushed into window.dataLayer as a GA4/GTM ecommerce event. No markup, so JS execution is required.
- medium Product — combined — JSON-LD, Microdata, Open Graph, and dataLayer all present at once (a realistic messy page).
- easy Collection (ItemList) — A category page exposed as a schema.org CollectionPage/ItemList.
- easy Product reviews — A product with visible reviews plus Review/AggregateRating JSON-LD.
- easy FAQ page — Common questions marked up as a schema.org FAQPage.
- easy Contact page — Email, phone, and address as plain text, mailto:/tel: links, Microdata, and Organization JSON-LD.
Pagination
Different pagination patterns for practicing crawling multi-page listings.
- easy Numbered pagination — Classic ?page=N style listing, 10 items per page, with rel="next"/"prev" link tags in <head>.
- easy Offset/limit pagination — Query-param offset/limit pagination.
- medium Load more button — Fetches additional items via a JSON API on button click.
- medium Infinite scroll — Loads more items automatically as you scroll.
Rendering modes
Content delivered differently: server-rendered vs. client-rendered.
- hard JS-rendered content — Empty shell on load; content is injected via a client-side fetch. Requires a JS-capable scraper.
- hard Frames & iFrames — Content nested inside an iframe pointing at a separate URL, two levels deep. Find the real page and fetch it directly.
Tables
Tabular data in a few different shapes.
- easy Simple table — A single flat product table.
- medium Sortable table — Client-navigable sortable columns via ?sort=&dir= query params.
- hard Nested/merged cells — Table grouped by category using rowspan.
Forms
Forms with varying complexity and hidden fields.
- easy Basic GET form — Simple search form, submits via GET.
- easy POST form — Form submission via POST with a confirmation page.
- hard Multi-step form — Three-step wizard using a session cookie to persist state.
- medium File upload — Upload form with a file input.
- hard Hidden & honeypot fields — Form with a CSRF token and a bot-trap honeypot field that must stay empty.
Authentication
Cookie/session-based login wall.
- medium Login page — Sets a session cookie on successful login (user: demo / pass: demo).
- medium Protected dashboard — Redirects to /login unless a valid session cookie is present.
- easy Logout — Clears the session cookie.
Dynamic elements
Elements that change between requests or after a delay, useful for checking selector robustness and explicit-wait logic.
- medium Dynamic elements — A randomized id on every request, plus buttons that only become enabled or change color after a delay.
Accessibility
The same page with and without intentional accessibility issues, documented on-page. Built for automated a11y scanners like axe-core, pa11y, or Lighthouse.
- medium Inaccessible version — Four documented, scanner-detectable issues: missing alt text, an unlabeled input, low contrast, and a skipped heading level.
- easy Accessible version — The same content with every issue above fixed, for comparison.
Link graphs
Crawling practice: pages for testing crawlers and link-following logic, including redirect chains, loops, and intentional dead ends.
- medium Redirect chain — Follows N sequential redirects before landing. Try /redirect-chain/{n}.
- medium Circular links — Three pages that link back to each other in a loop.
- easy Broken links — A page mixing valid links with intentional 404s.
Markup difficulty levels
The same product data rendered with progressively messier HTML.
- easy Clean semantic HTML — Well-structured HTML with meaningful classes.
- medium Div soup — Same content, all divs/spans, no semantic tags or classes.
- hard Obfuscated classes — Same content, hashed/randomized-looking class names.
- medium Data-attribute hooks — Same content, data extracted via data-* attributes rather than classes.
URL structure & normalization
The mechanics behind duplicate-content URLs: trailing slashes, case sensitivity, query parameter order, tracking params, and the <base> tag.
- easy Overview — Links to every URL-structure scenario below.
- easy Trailing slash — The same content at two URLs, one with a trailing slash, one canonical to the other.
- medium Case sensitivity — Paths are case-sensitive here; the lowercase variant of this URL is a genuine 404.
- medium Query parameter order & tracking params — A canonical tag computed from the request, sorting params and stripping known tracking params.
- medium Encoded characters — Shows the raw vs. decoded query string: %20, +, and a literal space.
- hard The <base> tag — A <base href> one directory above the page's own URL, so a relative link resolves somewhere unexpected.
Canonical tags & meta robots directives
Canonical tag scenarios (self, duplicate, conflicting, cross-domain) and page-level robots directives via both a meta tag and the X-Robots-Tag header.
- easy Overview — Links to every canonical and meta robots scenario below.
- easy Canonical: self-referencing — The recommended default: a page canonical to itself.
- medium Canonical: duplicate content, page A — The preferred URL in a duplicate-content pair.
- medium Canonical: duplicate content, page B — A different URL with the same content, canonical to page A.
- hard Canonical: tag vs. header conflict — The <link> tag names one URL, the HTTP Link header names another.
- medium Canonical: cross-domain — Canonical points at a URL on a different domain, the syndicated-content pattern.
- easy Meta robots: noindex, follow — Keep this page out of the index, but still crawl its links.
- easy Meta robots: index, nofollow — Index this page, but don't follow its outbound links.
- medium X-Robots-Tag header — The same noindex directive as an HTTP header instead of a meta tag, the only option for non-HTML resources.
- easy Meta robots: noarchive, nosnippet — Index this page, but don't cache a visible copy or show a snippet.
hreflang
Three language variants of the same page with reciprocal hreflang tags to each other, themselves, and an x-default.
- easy Overview — Links to all three language variants.
- medium English variant — hreflang="en", linking to the Spanish and French variants plus x-default.
Redirect mechanisms
Redirects that don't use a real HTTP 3xx status code, plus a genuine infinite redirect loop for testing loop-detection logic.
- easy Overview — Links to every redirect-mechanism scenario below.
- medium Meta refresh — A <meta http-equiv="refresh"> tag; the server response itself is a plain 200.
- hard JavaScript redirect — window.location set from a script, invisible to a scraper that skips JS execution.
- hard Infinite redirect loop — Two real HTTP 302s that point at each other forever, on purpose.
HTTP & Networking
Endpoints for testing HTTP clients, status codes, and headers directly.
Status & redirects
Control the exact status code and redirect behavior of a response.
- easy Status code echo — Returns the requested HTTP status code. Try /http/status/{code}.
- easy Redirect chain — Issues N sequential 302 redirects. Try /http/redirect/{n}.
- easy Redirect to URL — Redirects to any http(s) URL you supply via ?url=, with an optional ?status_code=.
- easy Delayed response — Delays the response by N seconds (max 10). Try /http/delay/{seconds}.
Headers & cookies
Inspect what your client is sending, or set state for it to send back.
- easy Header echo — Returns the request headers as JSON.
- easy Request echo — Accepts any method and echoes back the method, headers, query, and body. Try POSTing JSON to it.
- easy Set response headers — Every query param becomes a real response header, and is echoed in the JSON body.
- medium User-Agent check — Tests header-spoofing logic: returns 403 unless your User-Agent looks like a real browser.
- easy Your IP — Returns the connecting client IP as seen by the edge.
- easy Set cookie — Sets a cookie from query params, then redirects to /cookies/get.
- easy Get cookies — Returns current cookies as JSON.
Authentication
Protected endpoints covering common HTTP-level auth schemes.
- easy Basic auth — Protected by HTTP Basic Auth (user: demo / pass: demo).
- easy Bearer token auth — Requires an Authorization: Bearer demo-token header.
Compression & rate limits
Response encoding and throttling behavior.
- medium Gzip response — A padded JSON body, transparently gzip-compressed by the edge when the client sends Accept-Encoding.
- medium Rate limiting — Returns 429 after 5 requests within 60 seconds from the same client.
Caching & conditional requests
Round-trip endpoints that exercise conditional GET (If-Modified-Since / If-None-Match) handling.
- medium Conditional GET — Returns Last-Modified/ETag headers; send either back to get a 304 with no body.
- medium ETag round-trip — Send the same value back via If-None-Match to get a 304. Try /http/etag/{value}.
Streaming & content negotiation
Chunked responses, byte-range requests, and Accept-driven content negotiation.
- medium Streamed NDJSON — Streams N newline-delimited JSON lines via a real ReadableStream. Try /http/stream/{n} (max 100).
- medium Byte-range requests — Supports Range: bytes=start-end with real 206/416 responses, for resumable-download testing.
- medium Image content negotiation — Returns a real SVG or PNG depending on the Accept header.
Mock Data
A small fake REST API for mocking data in your own apps. Responses are deterministic, JSONPlaceholder-style, and nothing is persisted.
Users API
A fake CRUD API for user records, supporting list, fetch, create, update, and delete (nothing is persisted).
- easy Users API reference — Every endpoint documented: list, get, create, update, delete, plus a generated avatar per user.
Posts & Comments API
Blog-style posts and their nested comments, backed by a fake CRUD API.
- easy Posts & Comments API reference — Endpoint reference covering nested /posts/:id/comments and ?userId=/?postId= filtering.
Albums & Photos API
Albums and their nested photos, each with a real self-hosted image, served through a fake CRUD API.
- easy Albums & Photos API reference — Covers nested /albums/:id/photos, plus generated per-photo images.
Todos API
To-do items with a deterministic completed/incomplete split, exposed through a fake CRUD API.
- easy Todos API reference — Documents every endpoint, including ?userId= and ?completed= filtering.
Generators
Instant, no-signup generators for bulk test data. Output is fresh every time, unlike the deterministic Mock Data fixtures above.
User Generator
Bulk fake identities (name, email, phone, address, avatar), fresh every time.
- easy Generate users — Interactive generator with instant JSON/CSV download. No signup or email required.
Card Generator
Synthetic, Luhn-valid test credit card numbers for exercising payment-form validation.
- easy Generate test cards — Visa, Mastercard, Amex, and Discover-shaped numbers. Not real, not linked to any account, and cannot be charged.
File Generator
Dummy files of a given type and size, for checking upload validation.
- easy Generate a dummy file — txt, csv, json, or random bytes, at any size up to 5MB.
Image Generator
A placeholder image at any dimensions you request.
- easy Placeholder image — Deterministic per dimension, unlike the other generators here. Try /generator/images/{width}/{height}.
AI & LLM Testing
Test fixtures for people building AI agents, LLM-feeding scrapers, and RAG pipelines. Includes prompt-injection isolation testing, a RAG testing dataset with a documented answer key, and RAG testing PDFs and documents built to stress-test extraction.
Prompt injection
A page with safe, labeled example injection patterns and a benign canary phrase, so you can check that page content stays isolated from an agent's instructions.
- medium Prompt injection test page — Seven hidden-text vectors (HTML comments, display:none, off-screen, color-matched, zero-font, alt text, meta description), each with a unique canary.
RAG & retrieval corpus
A small RAG testing dataset: fifteen short, topically distinct articles paired with a documented answer key, enough to test chunking, embedding, and retrieval end to end and check whether the right result comes back.
- easy Corpus & answer key — Every article in the dataset, plus sample queries mapped to the correct expected result.
- easy Example article — Available as HTML, plain Markdown, or PDF, and in bulk as JSON at /ai/corpus/articles.json.
- easy Full dataset bundle — The whole RAG testing dataset in one download: every article, every format URL, and the answer key in a single JSON file.
PDF documents
RAG testing PDFs for exercising PDF-to-text extraction, from simple single-column articles up to layouts built specifically to trip up naive parsers.
- easy PDF documents — Every RAG testing PDF on the site in one place, including a plain PDF version of each corpus article.
- medium Table extraction test — A drawn table (an order log) that tests whether extraction keeps each row's cells together instead of reading columns out of order.
- hard Two-column layout test — Two unrelated essays placed side by side to test whether extraction respects column boundaries instead of reading straight across the page.
- hard Running header/footer test — A multi-page document with repeated header and footer boilerplate on every page, testing whether extraction strips it out.