Proxies & ScrapingHUB

Best Residential Proxies for Web Scraping in 2026

Your scraper works for an hour, then every request comes back 403 — because datacenter IPs get flagged the moment the traffic stops looking human.

Some links on this site are affiliate links. If you buy through them, we earn a commission at no extra cost to you. We only recommend tools we would deploy ourselves.

$ ls ./sections
  1. Datacenter vs residential proxies: why one dies at scale
  2. What separates a real pool from a reseller
  3. The residential proxy ranking
  4. Wiring a rotating pool in Python
  5. Edge cases and troubleshooting

Your scraper ran clean for an hour, then every request came back 403 and the nightly job collapsed into a pile of challenge pages. Datacenter IPs get flagged the moment your traffic stops looking human, which is why residential proxies, routed through real consumer devices, are the only thing that survives past the first few hundred requests. The pool you pick decides whether the job finishes.

Datacenter vs residential proxies: why one dies at scale

Every datacenter IP you rent lives inside a handful of cloud ASNs. AWS, OVH, Hetzner, DigitalOcean: anti-bot vendors keep reputation scores on those autonomous systems, and a request arriving from a known cloud network starts the conversation already distrusted.

It does not matter how clean your code is. The IP wears a cloud uniform, and the challenge page is the bouncer checking it at the door.

A residential IP carries a different reputation. It belongs to an ISP that hands it out to somebody’s home router, so to the target it reads as an ordinary person on home broadband. That is the whole trick: you borrow the trust that consumer connections already have, including the messy reality of CGNAT where thousands of real users share one address.

The catch is that the IP is one signal among many. Modern anti-bot stacks fingerprint your TLS handshake (JA3/JA4), your HTTP/2 frame ordering, your header order, and the timing between requests. A residential IP is not a magic cloak; it is a clean starting reputation that a headless-Chrome fingerprint can still set on fire. At scale the failure becomes a cascade: once you trip the trust threshold on a flagged datacenter ASN, every request after it inherits the block, and no retry loop digs you back out.

Residential rotation resets that reputation on every call, which is exactly why it holds up when volume climbs.

What separates a real pool from a reseller

Half the outfits selling “residential” bandwidth are reselling the same underlying network with a new logo on the dashboard. Here is what actually decides whether a pool survives contact with a real target.

Unique IP breadth. The number that keeps a job alive is genuine IP diversity across many ASNs and countries. A pool advertising ten million addresses that quietly recycles the same thin slice of exit nodes gets you blocked as fast as a small one, so the headline total on the pricing page tells you almost nothing.

Rotation and sticky sessions. A good gateway rotates the exit IP on every request by default, and lets you pin a sticky session when you need one IP held across a multi-step login or a cart flow. If a provider cannot give you both per-request rotation and a controllable sticky TTL, it is not built for scraping.

Geo-targeting. Real pools let you target country, city, and sometimes ASN. That matters the second your target serves different HTML by region, or blocks everything outside its home market.

Sourcing ethics. This is the one nobody wants to discuss. A pool sourced through consent-based SDKs, where users opted in for a perk, is stable. A pool sourced through malware or bundled without consent is a legal liability and an operational one, because those IPs get discovered, torn down, and yanked out from under your running job. Ask any serious provider where the addresses come from; the ones worth paying refuse to be vague about it.

The residential proxy ranking

Quick disclosure: the provider links below are affiliate links. Sign up through one and the site earns a commission at no extra cost to you, and none of it changes the order below.

ProviderBest forPrice postureVerdict
Bright DataEnterprise targets, compliance, the hardest wallsPremium; enterprise-scale minimums, billed per GBBiggest, best-documented pool; you pay for it
OxylabsPython / Node teams shipping production scrapersUpper-mid; scales down better than it used toThe strong default
SmartproxyIndie and growth teams past the free-list stageApproachable; small commitments, no procurement meetingBest value in the middle tier
IPRoyalSpiky jobs, pay-as-you-go, no monthly lock-inMetered per GB, no subscription floorCheapest honest way to start

When your targets are the meanest anti-bot deployments on the web and Legal wants a paper trail on where every address came from, Bright Data is the pool with the most IPs and the most documentation standing behind them. It is the most expensive line on this page, and for a large data team that is the right trade, because you are buying uptime and a defensible sourcing story, and at that scale the bandwidth is the cheap part.

For most teams writing scrapers in Python or Node, Oxylabs is the one I reach for first. The pool is large, the rotating endpoint is boring to set up in the best possible way, and the docs assume you write code instead of clicking through a wizard. Building your own IP-rotation layer in 2026 is a waste of engineering hours, so route the requests through their gateway and let them eat the ASN bans.

Smartproxy sits in the middle of the market and earns the spot. You get smaller commitments than the enterprise tier, a pool deep enough for real geo-targeting, and pricing that does not require a purchase order. Once you have outgrown scraping free proxy lists and praying, this is the first paid tier that actually pays for itself.

When the workload is spiky and you refuse to pre-commit to monthly bandwidth, IPRoyal meters you by the gigabyte with no subscription floor. It is the honest place to start: pay for what a weekend crawl really burns, then move up a tier once the pipeline earns its keep.

Wiring a rotating pool in Python

With a rotating residential endpoint you do not manage a list of IPs. You point every request at one authenticated gateway host, and the provider’s network swaps the exit IP behind it. Here is a production-shaped requests client with backoff, jitter, and the status-code checks that actually matter.

import os
import time
import random
import requests

# Rotating residential gateway. The provider swaps the exit IP for you,
# so every request points at ONE host:port and their network picks the IP.
# Pull the real values from the provider dashboard after you sign up, and
# keep them in the environment. Never commit credentials to the repo.
PROXY_HOST = os.environ["PROXY_HOST"]        # e.g. "gate.provider.example:7777"
PROXY_USER = os.environ["PROXY_USER"]
PROXY_PASS = os.environ["PROXY_PASS"]

# One authenticated gateway URL, reused for http and https targets.
_GATEWAY = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}"
PROXIES = {"http": _GATEWAY, "https": _GATEWAY}

# A real browser UA. The proxy fixes IP reputation; the fingerprint is on
# you, so at least stop advertising python-requests in the header.
HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/124.0 Safari/537.36"
    ),
    "Accept-Language": "en-US,en;q=0.9",
}


def backoff(attempt):
    # Exponential wait with jitter. Jitter matters: a fleet of bots retrying
    # in perfect lockstep is itself a bot signal.
    return min(2 ** attempt, 30) + random.uniform(0, 1.5)


def fetch(url, max_retries=4, timeout=20):
    """GET through the rotating pool with retries and backoff.
    Read robots.txt and the target's ToS before you point this anywhere."""
    session = requests.Session()

    for attempt in range(1, max_retries + 1):
        try:
            resp = session.get(
                url,
                headers=HEADERS,
                proxies=PROXIES,
                timeout=timeout,
            )
        except requests.RequestException as exc:
            # Dead exit node, reset, or timeout: back off and let the gateway
            # hand us a fresh IP on the next attempt.
            wait = backoff(attempt)
            print(f"[net] {exc.__class__.__name__}: retry {attempt} in {wait:.1f}s")
            time.sleep(wait)
            continue

        if resp.status_code == 200:
            return resp

        if resp.status_code == 407:
            # Proxy auth failed. Retrying will not fix a bad password.
            raise RuntimeError("407 from the gateway: check PROXY_USER / PROXY_PASS")

        if resp.status_code in (403, 429):
            # The wall. Back off and rotate to a new exit IP.
            wait = backoff(attempt)
            print(f"[block] {resp.status_code} on attempt {attempt}, rotating in {wait:.1f}s")
            time.sleep(wait)
            continue

        # Anything else (5xx, unexpected redirects): surface it, do not swallow it.
        resp.raise_for_status()

    raise RuntimeError(f"Gave up on {url} after {max_retries} attempts")


if __name__ == "__main__":
    r = fetch("https://httpbin.org/ip")
    print(r.json())   # the exit IP, and it should change between runs

The three status checks are the whole game. A 200 is a win; a 403 or 429 is the anti-bot wall, so you back off and let the gateway rotate; a 407 means your proxy credentials are wrong and no amount of retrying will save you. The gateway host, port, and login come straight off the provider dashboard once you sign up, so drop them into environment variables or whatever secrets manager the rest of the stack I run already relies on. For a login or checkout sequence, swap the rotating endpoint for the provider’s sticky-session host so one exit IP is held across every step.

When to skip proxies and just buy the bypass

There is a reflex among engineers that reaching for a managed scraping API is admitting defeat. Buying the bypass does not make you a worse engineer. It makes you a faster one. Some jobs are simply not worth the standing cost of proxies plus a headless browser pool plus a fingerprinting arms race you have to keep re-winning every quarter.

ScrapingBee folds the proxy rotation, the headless rendering, and the challenge-solving into a single API call: you send a URL, you get HTML back. For a small team, paying per successful request to skip the entire anti-bot treadmill is a cheaper line on the invoice than an engineer’s afternoon spent staring at JA3 signatures. Whether it beats ZenRows at that specific job is its own fight, and I settle the ScrapingBee-versus-ZenRows head-to-head in its own teardown.

Edge cases and troubleshooting

None of this survives on a laptop that sleeps when you close the lid.

A rotating pool, retry loops, and sticky sessions all assume a process that stays up for hours, which is why the scraper belongs on a box built to run bots around the clock. Once it is on real infrastructure, here are the three failures that will actually page you.

Sticky-session leaks. You pin a sticky session for a login flow, then its TTL expires mid-sequence or you blow past the provider’s maximum hold time, the exit IP rotates under you, and the target logs you out or flags the account. Match the sticky TTL to how long the flow really takes, hit an IP-echo endpoint between steps, and re-authenticate the instant the observed exit IP changes.

Geo mismatch. You asked for US exits, but the gateway fell back to a random country because your city-level target had no free node, and now the site is serving the wrong currency or blocking you outright. Pass the country, and the city if you need it, explicitly on every session, then assert the geo with a quick IP lookup before the first real request instead of trusting the default.

Honeypot links. Some targets plant hidden <a> tags (display:none, zero-size, shoved off-screen) that no human would ever click, purely to catch crawlers that follow every href. Before you enqueue a URL, confirm its element is actually visible and honor rel="nofollow". Filter the DOM for visibility before you queue a single link, and the honeypots stop catching you.

stack used in this guide
TIER 1 · Residential proxies

Bright Data

PICK

The largest residential proxy network. Enterprise-grade, priced like it.

best for: Enterprise-scale scraping, hard targets Try Bright Data
TIER 1 · Residential proxies

Oxylabs

PICK

Premium residential & datacenter proxies, loved by Python/Node teams.

best for: Python & Node scrapers that need to just work Try Oxylabs
TIER 1 · Residential proxies

Decodo (Smartproxy)

Mid-tier residential proxies with a low entry price.

best for: Solo devs, social automation, side projects Try Decodo (Smartproxy)
TIER 1 · Residential proxies

IPRoyal

Cheap pay-as-you-go residential IPs.

best for: Low-volume jobs, no commitment Try IPRoyal
TIER 1 · Scraping APIs

ScrapingBee

PICK

Scraping API with headless rendering and proxy rotation baked in.

best for: Devs who want one API key, not an infra project Try ScrapingBee

→ the full stack

Found the fix? The tool that ends the problem is one click away.

The Stack