Integrations · Intermediate

Rotating and sticky proxies in Scrapy with a downloader middleware

Scrapy’s HttpProxyMiddleware supports authenticated HTTP proxies through request.meta["proxy"]. Configure the actual delivered gateway, propagate the setting to follow-up requests and verify the assigned session mode before increasing concurrency.

2 min read 4 sections Reviewed Editorial team Proxy Cyber

The simplest version#

Classify the response before retrying. A 403 may indicate an access rule that another IP will not resolve. For 429, respect Retry-After and reduce the request rate; use bounded backoff for temporary connection or server failures. Retry state-changing operations only when you can prevent duplicate actions.

spider.py
import scrapy

PROXY = "http://USER-cc-us:PASS@res.proxy-cyber.com:9000"

class PricesSpider(scrapy.Spider):
    name = "prices"
    start_urls = ["https://example.com/catalog"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, meta={"proxy": PROXY})

    def parse(self, response):
        for href in response.css("a.product::attr(href)").getall():
            yield response.follow(href, callback=self.parse_product, meta={"proxy": PROXY})

    def parse_product(self, response):
        yield {"url": response.url, "price": response.css(".price::text").get()}

A middleware for sticky sessions per item#

middlewares.py
import hashlib

class Proxy CyberMiddleware:
    GATEWAY = "res.proxy-cyber.com:9000"

    def __init__(self, user, password, country):
        self.user, self.password, self.country = user, password, country

    @classmethod
    def from_crawler(cls, crawler):
        s = crawler.settings
        return cls(s.get("KEY_PROXY_USER"), s.get("KEY_PROXY_PASS"), s.get("KEY_PROXY_COUNTRY", "us"))

    def process_request(self, request, spider):
        # Sticky when the request carries a session key (e.g. one per product flow), rotating otherwise
        key = request.meta.get("session_key")
        user = f"{self.user}-cc-{self.country}"
        if key:
            sid = hashlib.sha1(key.encode()).hexdigest()[:12]
            user += f"-sid-{sid}-ttl-10m"
        request.meta["proxy"] = f"http://{user}:{self.password}@{self.GATEWAY}"
settings.py
DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.Proxy CyberMiddleware": 350,   # before HttpProxyMiddleware (750)
}
KEY_PROXY_USER = "USER"
KEY_PROXY_PASS = "PASS"
KEY_PROXY_COUNTRY = "de"

CONCURRENT_REQUESTS = 32
CONCURRENT_REQUESTS_PER_DOMAIN = 8
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_TARGET_CONCURRENCY = 4.0
DOWNLOAD_TIMEOUT = 45
RETRY_ENABLED = True
RETRY_TIMES = 2
RETRY_HTTP_CODES = [408, 429, 500, 502, 503, 504, 522, 524]
COMPRESSION_ENABLED = True

Connection reuse and IP assignment are different controls. A client session reuses sockets; only the assigned gateway determines rotation and sticky-session behavior. Use the session parameters supplied with your service, and verify the exit over several requests. Closing a socket or sending Connection: close does not guarantee a different IP.

Keeping the bill down#

  • Scrapy does not load images or scripts; HTML and JSON only, so a page costs its HTML size.
  • Enable compression (default) and avoid Splash or browser rendering unless the data needs it.
  • Cache with HTTPCACHE_ENABLED = True during development so you do not pay to re-fetch the same pages while debugging selectors.

Per-domain politeness#

A pool is a way to be many polite visitors, not one impolite one. CONCURRENT_REQUESTS_PER_DOMAIN and AutoThrottle keep each target at a human-plausible rate per exit; the acceptable use policy forbids anything that looks like an attack.

Questions people ask#

Do I need scrapy-rotating-proxies?

Not with a gateway: rotation happens on the Proxy Cyber side for every new connection. That package manages lists of static proxies; with res.proxy-cyber.com there is one proxy to configure.

How do I use a different country per request?

Set request.meta["country"] in the spider and read it in the middleware to build the -cc- parameter; the example uses a single setting for brevity.

Your account

Manage your proxies in one account

Compare networks, place orders and follow your balance and support requests from one dashboard. Our team reviews payments and provides connection details after delivery.

Create account