Guide series · 23 guides

How to Avoid Getting Blocked While Scraping

To avoid getting blocked while scraping, make every request look like it comes from an ordinary visitor and keep the load low: rotate residential IPs, send a real browser's headers, pause randomly between requests, keep cookies within a session, render JavaScript only where the page needs it, and back off as soon as you see a 403, a 429 or a CAPTCHA. Most blocks come from three signals: the IP's network and reputation, too many requests from one IP, and a client that does not behave like a browser. ProxyField rotates requests across 412M+ residential IPs from $1.95/GB, at a 99.6% success rate, according to our service data; start with the Easy Trial: 1 GB for $2.95.

residential IPs
412M+
from, traffic never expires
$1.95/GB
Easy Trial
1 GB for $2.95
On this page 11 sections
  1. Why websites block scrapers
  2. The checklist
  3. IPs: rotation, sessions and the right type
  4. Headless browsers and stealth plugins
  5. CAPTCHAs and challenge pages
  6. How to spot and avoid honeypot links and crawler traps
  7. What to do when you get blocked
  8. Stay within the rules
  9. Guides on avoiding blocks
  10. Sources
  11. Blocks and anti-bot FAQ

Why websites block scrapers

Websites block scrapers to protect their servers, their data and their users' accounts, and bot-protection services score every request on a handful of signals. Knowing the signal tells you the fix.

Most blocks are made by an anti-bot service sitting in front of the site, not by the site's own code. The service scores each request and decides to allow it, slow it, challenge it with a CAPTCHA or block it. That is why a scraper can work for days and then fail everywhere at once: the scoring model changed, not your code.

Signal the site checksWhat gives a scraper awayThe fixGuide
IP network and reputationA datacenter IP, or an IP with a history of abuseResidential or mobile IPsWhy is my IP address blocked?, can websites detect proxies
Request rate per IPHundreds of requests a minute from one addressRotation, pauses, fewer threads per site429 errors
HTTP headersA library's default User-Agent, missing Accept-Language, odd header orderCopy a real browser's full header setHeaders for web scraping, what is a user agent
TLS and HTTP/2 fingerprintA Python or Go TLS handshake under a Chrome user agentA client that imitates the browser's handshake, or a real browserTLS and TCP fingerprinting
Browser fingerprint and JavaScript checksnavigator.webdriver = true, headless traces, a fingerprint that matches no real deviceA full browser, stealth patches, consistent profilesWhat is a browser fingerprint, browser fingerprinting in scraping
BehaviorPerfectly regular timing, no mouse or scroll, deep links with no referrerNatural pacing and navigation orderItem 10 of the checklist below
TrapsFollowing links that no human can see, or endless URL spacesSkip hidden links; normalize URLs and cap depthHoneypots and crawler traps below

Blocks rarely come from one signal alone. A datacenter IP with perfect headers may pass a news site and fail a retailer; a residential IP with a script's TLS handshake can still meet a challenge page. Fix the signals that are easiest to change first: rate, headers and IP type.

The checklist

Work through the list in order: the first five items are the easiest to change, and the later ones matter on sites with a dedicated anti-bot service.

  1. Read the rules. Check robots.txt and the terms, and collect only public data. robots.txt rules "are not a form of access authorization" (RFC 9309), but they tell you which paths the site wants left alone: skip them. More: how to check if a website allows scraping.
  2. Look for an API or embedded JSON first. Many pages load their data from a JSON endpoint you can call directly, with fewer requests and fewer blocks.
  3. Don't download what hasn't changed. Cache pages and send conditional requests: If-None-Match with the stored ETag, or If-Modified-Since with the stored date. An unchanged page comes back as 304 Not Modified with no body (MDN: conditional requests), so a re-crawl costs a fraction of the requests and traffic.
  4. Slow down. Start with one request every few seconds per site, add random jitter, and raise the rate only while responses stay clean.
  5. Rotate IPs. Spread requests over many residential IPs; use a sticky session only when several requests must come from one visitor.
  6. Send headers that fit the site. On sites that welcome crawlers, a descriptive User-Agent with a contact URL is the lowest-friction choice, for example PriceWatchBot/1.2 (+https://example.com/bot; [email protected]): the operator can see who you are and reach you instead of blocking you. On sites that serve only browsers, send a current browser User-Agent with the matching Accept, Accept-Language and Accept-Encoding, in the browser's order, and rotate whole header sets, not single fields. User agent list.
  7. Keep sessions consistent. One IP, one user agent and one cookie jar per session; a session that changes IP or browser in the middle looks like a takeover.
  8. Match the location. Use IPs in the country, and if needed the city, of the content you need; set the matching language and time zone in a browser.
  9. Use a browser only where needed. Plain HTTP for server-rendered pages; a headless browser for pages built by JavaScript: scrape dynamic web pages.
  10. Act like a visitor. Follow links rather than jumping to deep URLs in a perfect sequence, load the pages a visitor would load, and vary the timing.
  11. Fix your browser's fingerprint. Remove automation flags and keep fingerprints consistent with the user agent: fingerprint spoofing.
  12. Avoid traps. Never follow hidden links, fill hidden form fields or wander into endless URL spaces: honeypots and crawler traps.
  13. Back off by the numbers. On a 429 or 503, wait the Retry-After time if the response sends one: it holds either a number of seconds (Retry-After: 120) or an HTTP date (Retry-After: Wed, 28 Oct 2026 07:28:00 GMT), so parse both (MDN: Retry-After); otherwise wait 2, 4, 8, then 16 seconds with random jitter, and give up on the URL after 5 tries. After a 403 or a CAPTCHA, wait longer (20, 40, then 80 seconds, at most 3 tries) and continue on a new session. Never retry in a tight loop. Details: 429 errors, CAPTCHAs.
  14. Monitor. Log status codes and response sizes per site; a rise in 403s or in tiny pages is the early warning.

IPs: rotation, sessions and the right type

The IP is the first thing a site checks and the easiest one to change.

  • Residential IPs belong to home internet providers and look like ordinary visitors; they are the default for protected sites. Mobile IPs are shared by many phone users behind carrier NAT, so blocking one can lock out many real visitors; that makes them the next step for the strictest sites. Datacenter IPs cost less per GB ($0.29 down to $0.22 at ProxyField) but sit in ranges that sites can block by network. The types compared: types of proxies.
  • Rotation gives each request a new IP, so no single address crosses a rate limit. ProxyField can give you a new IP on every request.
  • Sticky sessions keep one IP for a set time, for logins, carts and paginated searches; ProxyField's last from 30 seconds to 36 hours.
  • Location matters: many sites serve or block by country. ProxyField targets country, region and city, in 195+ countries and all 50 US states.
  • IP ranges: sites and anti-bot services often block a whole subnet, or every range that belongs to a hosting provider, which is why datacenter proxies on one subnet can fail together. Residential IPs spread across many home internet providers and many ranges, so a range block hits far fewer of them.
  • Google: the pool is clean for Google, checked and segmented. If you want Google results as data rather than pages, the Google SERP API returns the results page as JSON, at $1.20 down to $0.80 per 1,000 successful results.

A proxy changes the IP and nothing else. If headers, fingerprints or behavior give you away, a new IP only moves the block to the next request; the rest of this checklist matters as much.

Headless browsers and stealth plugins

A headless browser renders JavaScript like a real browser, but out of the box it leaves automation traces such as navigator.webdriver set to true. Stealth plugins patch the best-known traces.

ToolStealth add-onWhat it does
Puppeteer (Node.js)puppeteer-extra with puppeteer-extra-plugin-stealthA set of evasions for headless Chrome's known tells
Playwright (Node.js)playwright-extra with the same stealth pluginThe Puppeteer evasions, through Playwright
Playwright (Python)playwright-stealthA port of the same evasions for Python
Selenium (Python)selenium-stealthSimilar patches for Selenium with Chrome or Chromium

A minimal Playwright example in Node.js, with a ProxyField residential IP in New York:

JavaScript
// npm install playwright playwright-extra puppeteer-extra-plugin-stealth
const { chromium } = require('playwright-extra');
const stealth = require('puppeteer-extra-plugin-stealth')();

chromium.use(stealth);

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://gate.proxyfield.io:7000',
      username: '<login>-country-us-city-new_york',
      password: '<password>',
    },
  });
  const page = await browser.newPage();
  await page.goto('https://api.ipify.org');
  console.log(await page.textContent('body')); // the proxy's IP
  await browser.close();
})();

Region, session and session time go in the same username: -region-<region>, -session-<id> and -ttl-<seconds> (30 to 129,600 seconds, 20 minutes by default), as in <login>-country-us-region-new_york-city-new_york-session-he9f2qga-ttl-600; every part after the login is optional.

Does playwright-stealth or puppeteer-extra-plugin-stealth still work?

Not reliably. The Node.js puppeteer-extra-plugin-stealth has had no release since 2.11.2 on March 1, 2023, and stealth plugins pass simple checks and public bot-test pages but, on their own, not a dedicated anti-bot service such as Cloudflare or DataDome. The Python playwright-stealth is maintained (2.0.3, April 4, 2026), and its own README warns it handles only "the simplest of bot detection methods". The Puppeteer plugin patches named traces of headless Chrome, with evasion modules such as navigator.webdriver, navigator.plugins, chrome.runtime, iframe.contentWindow, webgl.vendor, user-agent-override and window.outerdimensions. Its README says it passes "all public bot tests" (it links bot.sannysoft.com) and names the fpscanner, Intoli and areyouheadless tests. The same README calls the work "a rather interesting cat and mouse game", says "it's probably impossible to prevent all ways to detect headless chromium", and sets a narrower goal: to make detection so difficult "that it becomes cost-prohibitive or triggers too many false-positives". On reCAPTCHA v3 it says stealth "seems to help with maintaining a normal reCAPTCHA v3 score", calls the evidence "anecdotal observations", and warns that the score "is calculated individually per site". The Python playwright-stealth README is blunter: "Don't expect this to bypass anything but the simplest of bot detection methods."

Passing a public test page is not passing Cloudflare or DataDome, which also score the TLS handshake, the IP's reputation, the request rate and behavior. Cloudflare's bot detection engines, for example, run heuristics on every request, a machine-learning model that gives each request a bot score from 1 to 99, and optional JavaScript detections that, in Cloudflare's words, identify "headless browsers and other malicious fingerprints".

The same setup in Python with playwright-stealth 2.x (its Stealth().use_async wrapper applies the evasions to every page) and a ProxyField IP in New York:

Python
# pip install playwright playwright-stealth && playwright install chromium
import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import Stealth

PROXY = {"server": "http://gate.proxyfield.io:7000",
         "username": "<login>-country-us-city-new_york", "password": "<password>"}

async def main():
    async with Stealth().use_async(async_playwright()) as p:
        browser = await p.chromium.launch(proxy=PROXY)
        page = await browser.new_page()
        print(await page.evaluate("navigator.webdriver"))  # no longer True once stealth is applied
        await page.goto("https://api.ipify.org")
        print(await page.text_content("body"))              # the proxy's IP
        await browser.close()

asyncio.run(main())
What stealth patches can fixWhat they cannot change
navigator.webdriver set to trueThe TLS and HTTP/2 fingerprint of the connection
HeadlessChrome in the user agentThe IP's network and reputation
Missing plugins, languages and chrome.runtime objectsYour request rate and timing
WebGL vendor and window-size tellsBehavior: navigation order, no scrolling, deep links

Maintenance, from the npm and PyPI registries on October 27, 2026 (the release dates are the registries', not the READMEs'):

PackageLatest versionReleased
puppeteer-extra-plugin-stealth (npm)2.11.2March 1, 2023
playwright-extra (npm)4.3.6March 1, 2023
playwright-stealth (PyPI)2.0.3April 4, 2026
selenium-stealth (PyPI)1.0.6November 5, 2020

The Node.js plugins and selenium-stealth have had no release since 2023 or earlier, while browsers and detection keep changing; playwright-stealth for Python had a release in 2026. Use any of them together with residential IPs, real headers and calm pacing, not instead of them. More: can Playwright, Puppeteer and Selenium be detected, and the setup guides for Playwright, Puppeteer and Selenium.

CAPTCHAs and challenge pages

A CAPTCHA or "checking your browser" page means the site's protection has already scored your request as suspicious. The better answer is to avoid the score that triggers it, through the checklist above, rather than to solve challenges at scale. The guides:

How often a site challenges you depends on your whole request, not only the IP.

What to do when you get blocked

When a site starts blocking you, step back before you push harder.

  1. Stop and look at the response

    A 403 page, a 429 with Retry-After, a CAPTCHA or a 200 with an empty page each mean something different: proxy errors, 403 errors.

  2. Lower the rate

    And widen the pauses for that site.

  3. Check the request

    Against a real browser's: headers, cookies, TLS client.

  4. Change the IP type

    If datacenter IPs are refused: residential first, mobile for the strictest sites.

  5. Switch to a browser

    If the content needs JavaScript or the site sends a JavaScript check.

  6. Consider a scraping API

    If you would rather not run the browsers yourself: scraper API vs proxies. The ProxyField Web Scraping API fetches any URL, with JS rendering when the page needs it, billed on successful results only.

Change one thing at a time and measure the success rate after each step. If a site still refuses after all of this, stop: it is telling you it does not want automated visitors, and its terms may say the same.

Stay within the rules

Avoiding blocks is about not overloading sites and not looking like an attacker; it is not a license to take data you are not allowed to take. Scrape public pages, respect robots.txt and rate limits, never use logins you are not entitled to, and read what data is legal and safe to scrape. ProxyField's acceptable use policy forbids attacks, fraud, spam and access to data behind logins you are not entitled to.

Guides on avoiding blocks

Sources

Checked on October 27, 2026:

Blocks and anti-bot FAQ

How do I avoid getting blocked while web scraping?

ProxyField's rule from 412M+ residential IPs: keep the load low and look like an ordinary visitor. Rotate IPs across requests, start at one request every few seconds per site with jitter, send a real browser's full headers, keep each session on one IP and one cookie jar, render JavaScript only where the page needs it, and back off on the first 403, 429 or CAPTCHA (2, 4, 8, then 16 seconds) instead of retrying hard. ProxyField residential proxies cost from $1.95/GB, with a 99.6% success rate according to our service data.

What are web scraping practices to evade blockers?

The practices that work are the ones that make you look like a calm, ordinary visitor: modest request rates with jitter, residential IP rotation, realistic and consistent headers, a real browser for JavaScript pages, and no hidden-link crawling. Pair them with respect for robots.txt and the site's terms, which keeps you clear of the blocks aimed at abusive traffic.

How do I crawl a website without getting blocked?

Crawl from the sitemap or a known URL pattern, limit concurrency per host, honor robots.txt and any crawl delay, and spread requests over rotating IPs. Cache what you have already fetched so a re-crawl requests only new or changed pages.

Why do websites block web scrapers?

To protect their servers from load, their content and prices from competitors, and their users' accounts from abuse such as credential stuffing. Most blocking is automatic: a bot-protection service scores each request and blocks or challenges the ones that look automated.

How does bot detection affect web scraping?

It decides whether your request gets the real page, a challenge or an error. Detection combines the IP's network and reputation, the request rate, headers, the TLS fingerprint and, in browsers, JavaScript checks, so a scraper has to look ordinary on all of them, not just one.

How do I reduce bot detection when web scraping?

Remove the signals detection relies on rather than attacking the protection: use residential IPs, a real browser's headers and TLS handshake, a full browser with stealth patches for JavaScript checks, and human-like pacing. If a site still challenges every request, use its API, a scraping API or a slower schedule, or leave it.

How do I avoid getting blocked while scraping websites, beyond just adding proxies?

A proxy changes only the IP, so fix the other signals too: follow robots.txt, start at one request every few seconds per site with jitter, cache pages and send If-None-Match or If-Modified-Since so unchanged pages return 304, and send headers that fit the site. On a 429, wait the Retry-After time, or 2, 4, 8 and 16 seconds, at most 5 tries. Keep one IP and one cookie jar per session, use a real browser only for JavaScript pages, and skip hidden links and endless URL spaces.

My scraper got blocked. What should I do?

Stop sending from that IP, read the response (403, 429, CAPTCHA or an empty page), and lower the rate. Then compare your request with a real browser's, switch datacenter IPs for residential ones if they are refused, and resume slowly with retries and backoff.

How often can I scrape without getting blocked?

There is no universal number: it depends on the site's limits and your IPs. Start at one request every few seconds per IP with random pauses, watch the share of 403 and 429 responses, and raise the rate only while it stays near zero; with rotation, the per-IP rate stays low as the total grows.

Does playwright-stealth or puppeteer-extra-plugin-stealth still keep a headless scraper from being flagged as a bot?

Not reliably. The Node.js plugin's latest release, 2.11.2, dates from March 1, 2023; they hide traces such as navigator.webdriver and pass public test pages like bot.sannysoft.com, but not Cloudflare or DataDome on their own, and the Puppeteer plugin's author calls preventing all detection "probably impossible". They don't change your TLS handshake, IP reputation or behavior, so pair them with residential IPs and calm pacing; the Python playwright-stealth (2.0.3, April 2026) is maintained but warns it handles only the simplest checks.

Show 7 more questionsShow fewer questions

How does the Puppeteer stealth plugin hide automation?

It runs a set of evasions before each page loads: it removes navigator.webdriver, fills in browser objects and properties that headless Chrome lacks, and fixes details such as the Accept-Language header. You load it through puppeteer-extra with puppeteer.use(StealthPlugin()), or through playwright-extra for Playwright.

How do I avoid bot detection with Selenium?

Remove the automation switches (excludeSwitches: enable-automation), use a patched driver or the selenium-stealth package, and run a full rather than headless browser where possible. Keep the window size, language and time zone consistent with your user agent and IP location, and route the browser through rotating residential IPs in the site's country with natural timing. Proxy setup for Selenium is in our Selenium guide.

Why does Google block my scraper?

Google limits automated queries and checks the IP, the request rate and the client, so a script sending many searches from one IP soon meets an "unusual traffic" page. Spread queries over rotating residential IPs, keep the rate per IP low and send a real browser's headers. If you need the results as data, the ProxyField Google SERP API returns the results page as JSON, at $1.20 down to $0.80 per 1,000 successful results.

Can a website block an entire IP range?

Yes. Sites and anti-bot services often block a whole subnet or every range that belongs to a hosting provider, which is why datacenter proxies on one subnet can fail together. Residential IPs belong to many home internet providers and spread across many ranges, so a range block hits far fewer of them.

Does Node Unblocker help with web scraping?

Only a little. Node Unblocker is an open-source web proxy for Node.js that fetches pages through your own server and rewrites their links, so every request still leaves from that server's single IP. It can help with testing or with reaching a page from your server's location, but it adds no IP rotation, so it does not stop rate limits or IP blocks.

How do I check whether my proxy leaks my real IP in its headers?

Send a request through the proxy to a page that echoes the headers it receives and look for your own IP in X-Forwarded-For, Forwarded, Via or X-Real-IP; also check that the IP shown is the proxy's. The proxy checker runs the same test in a browser.

Easy Trial: 1 GB for $2.95.

Try for the price of 1 GB, no subscription, traffic never expires.