Web Scraping Without Getting Blocked: A Practical, Polite Playbook

Updated July 25, 2026

🛠️ This guide pairs with our free CSS & XPath Selector Tester — Test CSS selectors and XPath live against your HTML, then copy working scraper code.

Most scraper blocks aren’t sophisticated bot detection catching a clever adversary — they’re servers reacting sensibly to clients that behave nothing like the traffic they’re built for: hundreds of requests per second, no headers, no pauses. The fix is mostly to be a better-behaved client, which conveniently is also the ethical way to scrape. This playbook covers the techniques that keep legitimate scrapers running.

First: the checks that make blocking moot

  1. Is there an API? Many sites publish one — official APIs are faster, structured, stable, and often permit exactly the use you have in mind. Ten minutes of reading docs regularly saves weeks of scraper maintenance.
  2. Is the data in the sitemap or a feed? RSS/Atom feeds and XML sitemaps are published for machine consumption. Requesting exactly the pages listed there, once each, is the politest crawl possible — no discovery crawling, no wasted requests.
  3. What does robots.txt say? Compliant scraping starts with reading it (here’s how the rules work). Respecting it isn’t just ethics — Disallowed sections are frequently where the honeypots and aggressive rate limits live.
  4. Check the terms of service. Especially for anything commercial, logged-in areas, or personal data — the legal exposure is real and no header trick changes it.

Look like the browser you claim to be

The default user agent of every HTTP library (python-requests/2.32, curl/8.9) is an instant block on many sites. Two legitimate options:

Whichever you choose, keep it consistent per session; rotating identities mid-session is a detection signal in itself.

Rate limiting: the technique that matters more than all others

A human reads a page in 10+ seconds. A scraper hitting 50 pages/second is indistinguishable from a small DoS attack — and gets treated like one.

Don’t request what you already have

The least blockable request is the one you never send:

Handle the page you actually received

Blocks aside, most scraper “failures” are really parsing surprises: the server returned a login page, a consent interstitial, or an error page with a 200 status. Check for a sentinel element (the product title, the article body) before parsing, and fail loudly when it’s absent. Selector tips for markup that shifts: prefer stable attributes (id, data-*) over auto-generated class names, and XPath text anchors (//th[text()="Price"]/following-sibling::td) survive redesigns that class-based selectors don’t.

What this playbook deliberately omits

CAPTCHA-solving services, residential proxy rotation to evade IP bans, and header spoofing to defeat active anti-bot systems. Once a site is actively telling you no — CAPTCHAs, bans, legal notices — continuing is trespassing, whatever the technique. At that point the moves are: the API, a licensing conversation, or a different data source. Sustainable scraping is a cooperation problem, not an arms race: identify yourself or blend in honestly, go slow, cache hard, and take the data the site already publishes for machines.

Try the free CSS & XPath Selector Tester →