Set up Scrapy with ProxyField
- Put your ProxyField login and password in
PROXY_USERandPROXY_PASS. - Set
meta={"proxy": PROXY}on a request; the built-inHttpProxyMiddlewaresends it through the gateway. - For the whole project, add a downloader middleware that sets
meta["proxy"], ordered beforeHttpProxyMiddleware(750). - Run a spider against
https://api.ipify.org?format=jsonand check the IPs it logs.
One request through the gateway, with a New York exit IP.
import scrapy
PROXY = "http://<login>-country-us-city-new_york:<password>@gate.proxyfield.io:7000"
class IpSpider(scrapy.Spider):
name = "ip"
def start_requests(self):
yield scrapy.Request("https://api.ipify.org?format=json", meta={"proxy": PROXY})
def parse(self, response):
yield response.json()Scrapy's own reference for the proxy middleware: Downloader Middleware: HttpProxyMiddleware (Scrapy docs).
Mobile 5G/4G proxies cost $3.45/GB for 1 GB down to $2.45/GB from 1,000 GB, on the same gateway and the same balance.
On this page 10 sections
1. A proxy on one request
import os
import scrapy
PROXY = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@gate.proxyfield.io:7000"
class IpSpider(scrapy.Spider):
name = "ip"
def start_requests(self):
for _ in range(3):
yield scrapy.Request("https://api.ipify.org?format=json", meta={"proxy": PROXY}, dont_filter=True)
def parse(self, response):
yield response.json() # a different IP on each lineRun it with scrapy runspider ip_spider.py -o ips.json. HttpProxyMiddleware, on by default, reads meta["proxy"], turns the username and password in the URL into a Proxy-Authorization header, and opens an HTTPS tunnel for https:// URLs, so TLS runs from Scrapy to the site.
2. The proxy for the whole project
Rather than adding meta in every spider, set it once in a downloader middleware. In middlewares.py:
class ProxyFieldMiddleware:
def __init__(self, proxy):
self.proxy = proxy
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings.get("PROXYFIELD_URL"))
def process_request(self, request, spider):
request.meta.setdefault("proxy", self.proxy) # a spider can still override it per requestIn settings.py:
import os
PROXYFIELD_URL = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@gate.proxyfield.io:7000"
DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.ProxyFieldMiddleware": 350, # runs before HttpProxyMiddleware (750)
}The number matters: your middleware must run before HttpProxyMiddleware, which handles the credentials. Replace myproject with your project's package name. A quicker option for a test: HttpProxyMiddleware also reads the http_proxy and https_proxy environment variables when the crawl starts.
3. Rotating residential proxies in Scrapy
Scrapy has no rotation of its own, and with ProxyField you don't need a rotation package or a list: the gateway gives a new IP on every request, so one proxy URL rotates on its own.
- A new IP per request: the rotating username. Scrapy may reuse an open connection for several requests to the same site; if each request must get its own IP, check the IPs your spider logs, as in section 1. An open HTTPS connection keeps one exit IP until it closes.
- One IP for a sequence (a login and the pages behind it): a sticky session in the username, 30 s to 36 h, set per request in
meta. 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. Residential is the default; add-mobileafter the login for mobile IPs:<login>-mobile-country-us. - Several countries: a proxy URL per country, picked per request:
import os, random
def proxy_for(country):
return f"http://{os.environ['PROXY_USER']}-country-{country}:{os.environ['PROXY_PASS']}@gate.proxyfield.io:7000"
# in a spider or middleware
request.meta["proxy"] = proxy_for(random.choice(["us", "gb", "de"]))The -country- key follows the example <login>-country-us-city-new_york. Country keys outside the US: the two-letter country code in lowercase, as in -country-de.
When you change the proxy of a request, keep the credentials in the URL. Since Scrapy 2.6.2, HttpProxyMiddleware drops a stale Proxy-Authorization header when the proxy URL changes; on older versions, or if you set that header by hand, a rotated request can carry the previous login and fail with 407. Update Scrapy rather than managing the header yourself.
4. Pace and retries
The gateway accepts unlimited concurrent threads, so the limits to set are for the target site's sake:
CONCURRENT_REQUESTS_PER_DOMAIN = 8
DOWNLOAD_DELAY = 0.5
AUTOTHROTTLE_ENABLED = True
RETRY_ENABLED = True
RETRY_TIMES = 3
RETRY_HTTP_CODES = [429, 500, 502, 503, 504, 522, 524, 408]
DOWNLOAD_TIMEOUT = 60Leave 403 out of RETRY_HTTP_CODES: it usually means the site refused the request, and repeating it unchanged rarely helps. A retried request on a rotating username goes out from a new IP. More on refusals: 403 Forbidden When Scraping Through a Proxy.
5. JavaScript pages: scrapy-playwright and Splash
scrapy-playwright renders pages in a real browser, which takes the proxy in its launch options (or per browser context):
PLAYWRIGHT_LAUNCH_OPTIONS = {
"proxy": {
"server": "http://gate.proxyfield.io:7000",
"username": os.environ["PROXY_USER"],
"password": os.environ["PROXY_PASS"],
}
}Requests with meta={"playwright": True} then go through the proxy. For one IP per browser context, define contexts in PLAYWRIGHT_CONTEXTS, each with its own proxy, and pick one with meta["playwright_context"]. The same settings are explained for plain Playwright on Playwright proxy setup.
Splash takes the proxy as an argument of each render request:
from scrapy_splash import SplashRequest
yield SplashRequest(url, self.parse, args={"wait": 1, "proxy": PROXY})6. SOCKS5 and Scrapy
Scrapy's downloader does not support SOCKS proxies. Use the HTTP proxy URL above: ProxyField's gateway speaks HTTP, HTTPS and SOCKS5 on the same account, and HTTP covers everything Scrapy fetches. If another part of your stack needs SOCKS5, see SOCKS5 proxies.
Check and monitor the proxy
- Run the spider in section 1: each line should show an IP that is not your server's.
- Scrapy's stats at the end of a crawl count responses by status: watch
downloader/response_status_count/407(the login),/403and/429(the site) andretry/count. - A
407means the proxy did not accept the login: check the credentials, encode special characters withurllib.parse.quote, and update Scrapy if you rotate credentials. - Timeouts point to the port or a firewall: allow outgoing port
7000. - To test lines without a spider, use the proxy checker.
Gateway error messages: 407 Proxy Authentication Required for a wrong login or password, an IP not on the allowlist or a malformed location, 402 Payment Required when no traffic is left and 502 Bad Gateway when no exit could be connected; a restricted site gets no separate response, and a 403 comes from the site itself. Status codes are explained in proxy errors and HTTP Error 407 Proxy Authentication Required. Some site categories are restricted to protect the network, including financial and government services. Our 24/7 live chat helps with setup and integration.
Which proxies to use with Scrapy
| What your spider does | Proxy | Price |
|---|---|---|
| Crawl public pages at scale | Rotating residential | from $1.95/GB |
| Check what mobile users see | Mobile 5G/4G | from $2.45/GB ($3.45 for 1 GB) |
| Large crawls of sites that accept datacenter IPs | Datacenter | $0.29/GB down to $0.22/GB |
| Reach an API that allowlists one fixed IP | Dedicated ISP | from $2.29 per IP per 30 days |
If you would rather receive pages than run proxies, the Web Scraping API fetches any URL for $0.50 down to $0.20 per 1,000 successful results (plain HTTP) or $2.00 down to $1.00 with JS rendering, billed on successful results only, through Contact sales.
New to Scrapy? Start with Scrapy Tutorial: Build Your First Spider. For single requests outside a crawl, see Python requests. Use ProxyField for lawful work such as public web data collection, price and SEO monitoring and testing, within our acceptable use policy.
Get started
Start with the Easy Trial: 1 GB for $2.95, with no minimum purchase and no subscription. The traffic never expires and all purchases are final. See pricing per GB.
Scrapy Proxy Setup FAQ
How do I rotate residential proxies in Scrapy?
ProxyField rotates residential IPs for Scrapy at the gateway, from $1.95/GB ($2.95 for 1 GB): set meta["proxy"] = "http://<login>:<password>@gate.proxyfield.io:7000" on each request, or once in a downloader middleware, and every request gets a new IP. You don't need a proxy list or a rotation package.
How do I set up a proxy in Scrapy?
Add meta={"proxy": "http://<login>:<password>@gate.proxyfield.io:7000"} to a scrapy.Request. The built-in HttpProxyMiddleware routes the request through the proxy and sends the login from the URL.
How do I set one proxy for every request in a Scrapy project?
Write a downloader middleware whose process_request sets request.meta["proxy"], and enable it in DOWNLOADER_MIDDLEWARES with a number below 750, so it runs before HttpProxyMiddleware. For a quick test, the http_proxy and https_proxy environment variables work too.
What is the Scrapy proxy middleware?
HttpProxyMiddleware, a downloader middleware that is on by default. It reads the proxy from request.meta["proxy"] or the environment, adds the Proxy-Authorization header from the URL's credentials and sends the request through the proxy.
What type of proxy works best for Scrapy?
ProxyField rotating residential proxies, from $1.95/GB, suit most crawls of public pages. Datacenter proxies at $0.29 down to $0.22/GB suit sites that accept datacenter IPs, and mobile 5G/4G IPs suit pages that differ for phones.
Why use proxies with Scrapy?
A crawl sends many requests to one site, and sites limit requests per IP. Proxies spread the crawl over many IPs and let you fetch pages as visitors in another country see them.
Does Scrapy support SOCKS5 proxies?
No, Scrapy's downloader supports HTTP and HTTPS proxies only. Use ProxyField's HTTP proxy URL; it covers everything Scrapy fetches.
Does Scrapy support HTTP proxies with a username and password?
Yes. Put the credentials in the proxy URL, http://<login>:<password>@host:port, and HttpProxyMiddleware sends them in the Proxy-Authorization header. Encode special characters in the password.
How do I set a random proxy per request in Scrapy?
In a middleware or spider, set request.meta["proxy"] to a URL picked at random, for example one per country. With ProxyField's gateway, the same URL already gives a new IP on every request.
Do I need a rotating proxy middleware in Scrapy?
Not with a rotating gateway. Rotation packages manage a list of proxies and drop dead ones; ProxyField's gateway rotates IPs itself and moves traffic to the next node if one slows down.
Show 9 more questionsShow fewer questions
Why does Scrapy keep the old Proxy-Authorization header when I rotate proxies?
Older Scrapy versions kept the header when the proxy URL changed, so a rotated request carried the previous login. Scrapy 2.6.2 and later drop it when the proxy changes; update Scrapy and keep the credentials in the proxy URL.
What does a 407 response mean in a Scrapy log?
The proxy did not accept the login: a wrong username or password, special characters that need encoding, or a stale header after rotating credentials. Fix the credentials in the proxy URL and update Scrapy.
How do I check if a proxy is working in Scrapy?
Crawl https://api.ipify.org?format=json through the proxy a few times with dont_filter=True and look at the IPs; they should not be your server's. Then watch the 407, 403 and 429 counts in the crawl stats.
How do I monitor and optimize proxies in Scrapy?
Watch the response status counts and retry/count in Scrapy's stats, enable AutoThrottle, and set per-domain concurrency and a delay for each site. Rising 429s mean slow down; rising 407s mean check the login.
Why does Scrapy get blocked when curl from the same machine works?
Scrapy sends many requests quickly with its own headers, while a single curl request looks like a one-off. Slow the crawl down, send ordinary browser headers and keep to the site's limits; rotating IPs spread the load, but they don't make a refused request acceptable.
How do I use a proxy with scrapy-playwright?
Set PLAYWRIGHT_LAUNCH_OPTIONS = {"proxy": {"server": "http://gate.proxyfield.io:7000", "username": ..., "password": ...}}, or a proxy per context in PLAYWRIGHT_CONTEXTS. Requests with meta={"playwright": True} then use it.
How do I use a proxy with Splash?
Pass the proxy URL as the proxy argument of the render request, for example SplashRequest(url, args={"proxy": "http://<login>:<password>@gate.proxyfield.io:7000"}). Splash fetches the page and its resources through it.
Can I use free proxies with Scrapy?
You can, but free public proxies are slow, shared and often already blocked, so a crawl spends most of its time on errors and retries. ProxyField has no free proxies; the smallest purchase is 1 GB for $2.95.
What are Scrapy proxies?
Proxies a Scrapy crawl sends its requests through, set in request.meta["proxy"] or a middleware. Any HTTP proxy works; rotating residential ones suit crawls of sites that limit requests per IP.