scrapy

How to Set Up Proxy Credentials in Scrapy

Published 15 Sep 2026 · scrapy, proxy, authentication, middleware

How to Set Up Proxy Credentials in Scrapy

1. When Scrapy proxy credentials matter in a crawl

Scrapy projects hit this problem fast: the proxy works, then the target site starts asking for authentication. That is common with rotating services, private datacenter pools, and fixed corporate proxies. If you are figuring out how to set up proxy credentials in Scrapy, the key point is simple: this belongs in spider code or middleware, not in shell-level network settings.

A proxy with a username and password changes request handling at the point where Scrapy builds the request. A terminal setting cannot decide which spider gets which proxy, or which retry should switch to a second credential set. Scrapy is doing the HTTP work itself, so the proxy decision has to sit close to the request object. That keeps the behavior tied to the crawl, not the machine.

Think of a crawl with 3 targets. One domain allows a shared proxy, one domain wants a dedicated login, and one endpoint blocks the first proxy after 20 requests. If you set the proxy at the OS level, all 3 requests look the same. If you set it in Scrapy, each request can carry its own proxy details. That difference matters on the first failed response.

Scrapy also makes the proxy decision visible in the code path. You can inspect a spider, a downloader middleware, or a request callback and see exactly where the proxy is assigned. That is harder to do when the proxy lives in the shell profile of a developer’s laptop. One place. One decision.

2. Choose where the credentials will live in your Scrapy project

There are 4 practical places to keep proxy credentials in a Scrapy project: settings.py, spider-specific settings, environment variables, or a custom middleware config. Each one has a narrow use case. A global credential for one crawl can live in settings.py; a spider that targets one vendor can carry its own setting; environment variables fit deployment; middleware config helps when several spiders share the same login format.

Hardcoding credentials in source is the worst option, even for a private repository. A commit gets copied, mirrored, cached, and reviewed by more people than you expect. One accidental push is enough. Store only the name of the setting in code, then inject the secret at runtime. That keeps the Scrapy project portable and avoids a cleanup job later.

If your team already uses configuration files, keep the proxy username and password out of the spider class itself. Put the values in deployment-time variables, then read them with os.environ or a settings loader. For a quick local test, a temporary settings.py value can work, but treat it as disposable. It should not survive the week.

For a broader primer on the surrounding terms, the VPN and proxy glossary can help when a project mixes proxy, VPN, and auth language in the same ticket. Small distinction, big payoff. A proxy credential is not the same thing as a VPN login.

3. Add a proxy with credentials through request metadata

The most direct method is to attach an authenticated proxy to one request at a time. Scrapy supports request metadata, and the proxy key sits there cleanly. That gives you per-request control, which is useful when one crawl needs multiple proxy identities or when a single spider touches pages with different access rules.

A typical request can carry the proxy like this:

yield scrapy.Request(
    url,
    callback=self.parse_page,
    meta={
        "proxy": "http://user:[email protected]:8000"
    }
)

That example is plain on purpose. It shows the structure, not a full spider. The request carries the proxy in meta, and Scrapy routes that request through the authenticated proxy. If the proxy provider requires a different scheme, change the prefix to match the service. One request can use one proxy; the next request can use another.

There is a useful side effect here. You can keep login-heavy endpoints on one proxy while letting public pages travel through a different one. That reduces noise in logs and makes retries easier to reason about. If a single request fails, you know which proxy was in play because the proxy is attached to that request object, not hidden in some global layer.

A practical detail: do not scatter proxy strings through a dozen callbacks. Put the proxy assignment in one helper method, then call that helper wherever the spider needs it. Even a small spider becomes easier to audit when the proxy logic lives in one place.

4. Inject proxy credentials from a downloader middleware

For a larger Scrapy project, a downloader middleware is often the cleaner option. The middleware can assign request.meta["proxy"] for all matching requests, and it can do the same for a login header or other auth handling if your proxy service expects it. That keeps the spider code focused on target pages instead of credential plumbing.

This works well when the rule is simple: all requests from spider A use one proxy, or all requests to one domain use one authenticated proxy. A middleware can inspect the URL, the spider name, or a custom request flag, then set the proxy before the request reaches the downloader. No manual repetition. No copy-paste in callbacks.

Here is the shape of the logic:

class ProxyAuthMiddleware:
    def process_request(self, request, spider):
        if getattr(spider, "use_proxy", False):
            request.meta["proxy"] = spider.proxy_url

That snippet is minimal, and it should stay that way. The real project may add credential selection, domain checks, or per-spider overrides. The important part is placement. Middleware handles the request before download, which is exactly where proxy assignment belongs if the same rule applies broadly.

One small aside: if the proxy service expects a separate auth header rather than credentials in the proxy URL, the middleware is still the right place. You can build the header once, then reuse it across requests. That prevents each spider from reinventing the same code.

For related setup decisions, the proxy authentication best practices guide is worth a look if your team needs a policy for where auth logic should live. That matters most once more than one spider shares the same proxy account.

5. Handle proxies that need username and password formatting

Authenticated proxy URLs usually follow a simple pattern: scheme, username, password, host, and port. In many Scrapy setups, the credentials can be embedded directly in the proxy URL, as in http://user:pass@host:port. The exact format depends on the proxy type and provider, so check the service documentation before shipping code to production.

There are 2 common patterns. In the first, the proxy URL already contains the username and password, and Scrapy reads the whole string from request.meta["proxy"]. In the second, the proxy host is stored separately and the auth data is managed elsewhere, often by a middleware or by a provider-specific rule. The first pattern is easier to test. The second is easier to centralize.

If you do embed credentials in the URL, treat the string like a secret. It will show up in logs if you print request objects carelessly. It may also appear in debugging tools or stack traces. One leaked URL is enough to expose the account. That is a security mistake, not just a messy log line.

Some proxy providers use usernames with extra segments, such as zone names, session IDs, or country tags. That can change the URL format enough to break a copy-pasted example. Read the provider’s format once, then encode it exactly once in code. The proxy should match the provider, not the other way around.

6. Verify that Scrapy is actually using the authenticated proxy

Checking the request is not enough; you want proof that Scrapy is sending traffic through the authenticated proxy. The first place to look is the log output. If your middleware or spider prints the assigned proxy, you should see the expected host and port at the request stage. If the log shows no proxy at all, the request never picked up the setting.

Middleware order matters here. A later middleware can overwrite an earlier proxy assignment, and that can happen quietly. If one middleware sets the proxy and another one modifies the request, inspect the order in settings.py. One misplaced class can turn a valid authenticated proxy into a plain outbound connection. That mistake is easy to miss on small crawls.

Response behavior also tells you a lot. A proxy with the wrong credentials often returns a 407 status, while a valid proxy may return the target page, a block page, or a different IP echo response. If you test against a service that reports your IP, compare the output with the expected proxy location. You can also cross-check how to verify your IP is what you expect before you trust the crawl.

One practical check: run 5 requests with logging turned up, then compare the proxy host on each line. If all 5 requests point to the same authenticated proxy, your middleware or request metadata is working. If one request ignores the proxy, look for a callback that builds its own request without the shared helper. That happens more often than teams admit.

7. Rotate or switch proxy credentials per domain or request type

Some Scrapy jobs need more than one credential set. A retail site may allow one proxy account for product pages and another for checkout pages. A search crawl may need different proxies by domain, or a retry might need a fresh session identifier. In that case, the proxy decision should happen on a simple rule: by domain, by spider name, or by request type.

The cleanest place for that logic is usually the middleware, because it can inspect every outgoing request before download. You can switch credentials when the target domain matches a list, or when a request carries a custom flag like meta["proxy_group"]. That keeps the spider readable and avoids hardwired branches in every callback.

Retries deserve special handling. If one proxy gets blocked after 2 attempts, a retry can pick a different credential set before the request is sent again. That is not the same as random rotation; it is a controlled fallback. For a broader approach to this pattern, see the proxy rotation for web scraping guide. It pairs well with Scrapy’s retry logic.

There is a limit here. If you rotate credentials too aggressively, debugging becomes noisy. A request that changes identity on every retry is harder to trace, especially when a site returns inconsistent blocks. Start with 2 or 3 credential groups, then add more only when the crawl shows a clear reason. That restraint pays off.

8. Keep proxy credentials out of source control

Secret handling is the last thing people fix and the first thing that bites them later. Keep proxy credentials out of source control by reading them from environment variables at runtime, then injecting them into Scrapy settings or middleware config during deployment. That works on a laptop, a container, and a CI job without changing spider code.

A deployment pipeline can set PROXY_URL, PROXY_USER, or PROXY_PASS before Scrapy starts. The spider then reads those values and builds the authenticated proxy string. This keeps the codebase clean and makes credential rotation a config task, not a code change. One password change should not require a new commit.

Be careful with logs, test fixtures, and example files. A fake proxy string in a test can still look real enough to get copied into a ticket. A .env file should stay out of the repository. A deployment secret should stay in the deployment system. Those two boundaries are simple, and they are easy to blur if a deadline is close.

If your project uses multiple proxy vendors, document which setting names belong to which provider. A teammate who sees PROXY_URL and SESSION_ID should know whether those values are required or optional. For a broader look at privacy tooling that sits beside Scrapy, the VPN, proxy & privacy guides page can help connect the dots without mixing the code paths. Scrapy still needs its own proxy logic.

One last implementation point: test secret injection with a dummy proxy account before you run a production crawl. If the dummy account fails, you catch the error in a safe place. If it works, you know the proxy credential path is wired correctly. Then the real crawl can start with fewer surprises.

Private VPN & proxies from s4m

WireGuard VPN, SOCKS5/HTTP proxies and dedicated IPs. No logs, RAM-first.

See plans