How to Avoid Getting Blocked When Web Scraping
To avoid getting blocked when web scraping, distribute requests across rotating residential proxies, send realistic browser headers, pace and randomise your requests, target the right location, and handle errors with backoff. Most blocks come from sending too many requests from one IP or looking obviously automated.
- anti-bot
- web scraping
- fingerprinting
- captcha

Table of contents
Blocks feel arbitrary until you understand that detection runs as a pipeline. Each layer is cheaper than the next, so sites evaluate them in order and stop as soon as something looks wrong. Debugging works the same way: fix layer one before touching layer four, or you will spend money on proxies to solve a header problem.
| Layer | What it checks | Cost to the site |
|---|---|---|
| 1. IP reputation | ASN, hosting range, blocklists | Near zero |
| 2. Request shape | Headers, order, TLS signature | Very low |
| 3. Rate and pattern | Frequency, regularity, sequence | Low |
| 4. Browser environment | JS execution, canvas, WebGL | Moderate |
| 5. Behaviour | Mouse, scroll, timing between actions | High |
| 6. Challenge | CAPTCHA, proof of work | Highest, and costs real users too |
1. Rotate IPs with residential proxies
The single biggest factor is the IP. Use rotating residential proxies so each request, or each small batch, comes from a different real home IP. This prevents the rate limits and bans that hit a single repeating address, and it clears systems that filter datacenter ranges outright.
One caveat that catches people: rotating harder does not always help. If the site is scoring your request *shape* rather than your address, every new IP simply delivers the same suspicious request from somewhere new. If your block rate is unchanged after switching to residential, the problem is layer two.
2. Send realistic headers
This is where most scrapers are identified, and it is free to fix.
- Set a real, current User-Agent and keep it plausible — a Chrome version from three years ago is a signal in itself.
- Send the full set.
Accept,Accept-Language,Accept-Encoding,Referer, and theSec-Fetch-*andSec-CH-UAheaders modern browsers include. - Match header order. Browsers send headers in a consistent order; most HTTP libraries do not. Order alone can distinguish a real Chrome from a library claiming to be one.
- Keep the set coherent. A Chrome user-agent paired with headers Chrome never sends is worse than an honest one.
- Do not rotate user-agents within one session. A browser that changes identity between two requests is more suspicious than one that stays boring.
TLS fingerprinting
The layer beneath headers, and the one that quietly defeats otherwise well-built scrapers. Every TLS client presents a distinctive combination of cipher suites, extensions and ordering — Chrome's differs from Python's requests, which differs from Go's standard library. Sites match against known signatures, so a request can be flagged before a single HTTP header is read.
You cannot fix this with headers. The options are to use a client that mimics a browser's TLS handshake, or to run an actual browser via Playwright or Puppeteer and accept the bandwidth cost.
If your scraper works from a browser and fails from a script against the same IP, stop adjusting headers. You are being identified below HTTP.
3. Pace and randomise requests
Add delays between requests and randomise them. Aggressive, perfectly timed bursts are an obvious bot signal — and so is a perfect two-second interval, because no human is that consistent. Draw from a distribution rather than a constant, and slow down more on error responses than on successes.
Rough starting point: 1–5 seconds between requests to one host, randomised, with concurrency spread across IPs rather than stacked on one. Then tune against the site's actual tolerance rather than against a number from a blog post.

4. Use sessions where needed
For multi-step flows — login, pagination, carts — use sticky sessions to keep the same IP for the whole sequence, then rotate between sequences. For independent page fetches, rotate per request. Getting this backwards produces symptoms that look exactly like detection but are self-inflicted; rotating vs sticky sessions covers the diagnosis.
5. Target the right location
Use country or city targeting so the IP location matches the content you are collecting. This improves accuracy and looks natural — but the stronger reason is consistency. An Accept-Language of de-DE arriving from a Brazilian IP with a New York timezone is three signals that disagree, and disagreement is what gets scored.
Clean IPs, city-level targeting
Residential proxies with country, city and ASN selection across our full location coverage.
6. Handle errors gracefully
- 1Classify the failure. A timeout, a
429, a403, a challenge page and a genuine404need different responses — the error code reference covers which is which. - 2Detect soft blocks by content, not status. A
200carrying a challenge page is the most common modern block. - 3Back off exponentially and rotate the exit — but back off first. Retrying immediately on a fresh IP teaches the site that its rate limit is being evaded.
- 4Cap retries and quarantine problem URLs rather than looping.
- 5Log the exit IP with every failure. Without it you cannot tell a bad exit from a bad request.
Reading the symptoms
| Symptom | Most likely layer | First thing to try |
|---|---|---|
| Blocked from the very first request | IP reputation | Switch to a residential exit |
| Works in a browser, fails in a script | TLS or headers | Match the browser's handshake |
| Success rate decays over a run | Rate and pattern | Slow down, spread across more exits |
200 with missing fields | Soft block | Assert on content, validate responses |
| CAPTCHAs partway through | Rate and pattern | Reduce per-IP throughput |
| Challenged even in a real browser | Behaviour | Reconsider whether to scrape this target |
Do proxies stop CAPTCHAs?
They reduce them substantially, because a clean residential IP does not trip the reputation check that triggers most challenges. They do not eliminate them. A CAPTCHA appearing partway through a run is almost always a rate signal, not an IP signal — the answer is to slow down, not to buy better proxies.
Proxies remove the IP bottleneck; clean headers, pacing and good error handling do the rest. Always respect robots.txt and the site's terms.
Sources
Frequently asked questions
Why do I keep getting blocked when scraping?
Usually because too many requests come from one IP, you're using detectable datacenter IPs, or your requests look automated through missing or oddly ordered headers and no delays. Rotating residential proxies plus realistic headers and pacing fix most cases.
Do proxies stop CAPTCHAs?
Clean residential IPs greatly reduce CAPTCHA frequency because they look like real users. Combine them with good request hygiene; for the toughest sites you may still need a CAPTCHA-solving step.
How slow should my scraper be?
A common starting point is 1–5 seconds between requests with randomisation, adjusted to the site's tolerance. Rotating IPs lets you parallelise while keeping per-IP rates low.
What is TLS fingerprinting and how do I get around it?
Every TLS client presents a distinctive combination of cipher suites and extensions, so a site can identify Python's requests or Go's standard library before reading a single HTTP header. Headers cannot fix it. Either use a client that reproduces a browser's TLS handshake, or drive a real browser.
My scraper works in a browser but not in code. Why?
Almost always a request-shape problem rather than an IP problem. The browser sends a different TLS signature, a complete and correctly ordered header set, and executes JavaScript your script does not. Test from the same IP in both to confirm the address is not the variable.
Should I retry immediately after a block?
No. Back off first, then retry on a different exit. Retrying instantly on a fresh IP looks like deliberate evasion and tends to escalate the site's response rather than get you through.
Is rotating my user agent on every request a good idea?
Not within a session. A browser does not change what it is between two requests, so rotation there is itself a signal. Vary the user agent between sessions and keep it fixed and coherent with the rest of your headers inside one.
The seamless team runs residential, ISP and datacenter proxy infrastructure and writes these guides from day-to-day operational experience.
Ready to try seamless proxies?
Residential, ISP and datacenter proxies with no data expiry.
Browse PlansKeep reading
How to Choose the Best Proxies for Web Scraping
Which proxy type to use, how to size your pool, how rotation and geo-targeting work, and the response-quality checks that catch silent failures.
GuidesWhat Is Web Scraping?
What web scraping is, the pipeline behind it, where it is used, what it costs, and why proxies stop being optional the moment you scale.
GuidesRotating vs Sticky Proxy Sessions Explained
When to rotate IPs on every request and when to hold one — with a decision rule, session-length guidance and the bugs each choice causes.
