PINGDOM_CHECK

#ExtractSummit2026 The world's largest web scraping conference returns. Austin Oct 7–8 · Dublin Nov 10–11.

Register now
Data Services
Pricing
Login
Try Zyte APIContact Sales
  • Unblocking and Extraction

    Zyte API

    The ultimate API for web scraping. Avoid website bans and access a headless browser or AI Parsing

    Ban Handling

    Headless Browser

    AI Extraction

    SERP

    Enterprise

    DocumentationSupport

    Hosting and Deployment

    Scrapy Cloud

    Run, monitor, and control your Scrapy spiders however you want to.

    Coding Agent Add-Ons

    Agentic Web Data

    Plugins that give coding agents the context to build production Scrapy projects. Starts with Claude Code.

  • Data Services
  • Pricing
  • Browse

    • BlogArticles, podcasts, videos
    • Case studiesCustomer outcomes
    • White papersIn-depth reports
    • EventsConferences, webinars, recordings

    Subscribe

    • NewsletterSwiftly delivered
    • Discord communityExtract Data community
  • Product and E-commerce

    From e-commerce and online marketplaces

    Data for AI

    Collect and structure web data to feed AI

    Job Posting

    From job boards and recruitment websites

    Real Estate

    From Listings portals and specialist websites

    News and Article

    From online publishers and news websites

    Search

    Search engine results page data (SERP)

    Social Media

    From social media platforms online

  • Meet Zyte

    Our story, people and values

    Contact us

    Get in touch

    Support

    Knowledge base and raise support tickets

    Terms and Policies

    Accept our terms and policies

    Open Source

    Our open source projects and contributions

    Web Data Compliance

    Guidelines and resources for compliant web data collection

    Join the team building the future of web data
    We're Hiring
    Trust Center
    Security, compliance & certifications
Login
Try Zyte APIContact Sales

Zyte Developers

Coding tools & hacks straight to your inbox

Become part of the community and receive a bi-weekly dosage of all things code.

Join us
    • Zyte Data
    • News & Articles
    • Search
    • Social Media
    • Product
    • Data for AI
    • Job Posting
    • Real Estate
    • Zyte API - Ban Handling
    • Zyte API - Headless Browser
    • Zyte API - AI Extraction
    • Web Scraping Copilot
    • Zyte API Enterprise
    • Scrapy Cloud
    • Solution Overview
    • Blog
    • Webinars
    • Case Studies
    • White Papers
    • Documentation
    • Web Scraping Maturity Self-Assesment
    • Web Data compliance
    • Meet Zyte
    • Jobs
    • Terms and Policies
    • Trust Center
    • Support
    • Contact us
    • Pricing
    • Do not sell
    • Cookie settings
    • Sign up
    • Talk to us
    • Cost estimator
All articles
AI60, 60 articles
Data quality13, 13 articles
Developer interest57, 57 articles
Integration2, 2 articles
Open-source40, 40 articles
Proxies29, 29 articles
Scraping practice17, 17 articles
Scraping strategy26, 26 articles
Web data60, 60 articles
Web scraping APIs33, 33 articles
Zyte API59, 59 articles
Scrapy48, 48 articles
Scrapy Cloud10, 10 articles
Web Scraping Copilot12, 12 articles
AI & Machine Learning1, 1 articles
Automotive2, 2 articles
E-commerce & retail26, 26 articles
Entertainment & Streaming2, 2 articles
Financial Services8, 8 articles
Government2, 2 articles
Market Research & Intelligence3, 3 articles
Media & publishing8, 8 articles
Real Estate2, 2 articles
Recruitment & HR3, 3 articles
Transportation & Logistics2, 2 articles
Travel & hospitality2, 2 articles
Extract Summit25, 25 articles
PyCon1, 1 articles

Appearance

Discord Community
BlogProxiesDeveloper’s guide to rotating proxies in Python
ArticleGuideProxies

Developer’s guide to rotating proxies in Python

Correct use of rotating proxies is a key ingredient of web data extraction. In this guide, you will learn how to set up IP rotation for scraping in Python.

N

Neha Setia Nagpal

5 min read · April 8, 2022

Developer’s guide to rotating proxies in Python

A developer’s guide to rotating proxies in Python

A proxy is an intermediary server that hides your IP, so you can navigate through web traffic anonymously and securely. Proxies have very interesting use-cases, the most prominent of them being web scraping for pricing intelligence, SEO monitoring, data collection for market research, etc. And the correct use of rotating proxies is a key ingredient of this.

If you want to know more about proxies for web scraping and how proxies work, feel free to skim through our recent blog.

In this developer guide, you will learn how to:

  1. Set up a proxy using the Python library - ‘Requests’
  2. Use rotating proxies in three different ways
    1. Using Request library
    2. Using Scrapy rotating middleware
    3. Using Zyte’s Smart Proxy Manager

So let’s get started!

Prerequisites

  1. Requests: It is an elegant and simple HTTP library for Python. It allows you to send HTTP/1.1 requests extremely easily. There’s no need to manually add query strings to your URLs or to form-encode your POST data. To install the library, run this command in the terminal.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

python -m pip install requests

python -m pip install requests

  1. Scrapy: This is one of the most powerful, fast, open-source web crawling frameworks written in Python to extract structured data which can be used for a wide range of useful applications, like data mining, information processing, or historical archival. If you are new to scrapy, this tutorial on Scrapy would be a good place to start. Scrapy comes with a middleware that makes rotating proxies a breeze, once you have a list of working proxies.  To install scrapy and scrapy-rotating-proxies, run the following commands.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

pip install scrapypip install scrapy-rotating-proxies

pip install scrapypip install scrapy-rotating-proxies

  1. Zyte Smart Proxy Manager: This is a proxy management and antiban solution that manages proxy pools and handles bans so you can focus on extracting quality data. Follow this guide to create a Smart Proxy Manager account and get a 14-day free trial. You can cancel at any time and you won’t be charged a single penny for the free trial.

 To use Smart Proxy Manager with Scrapy, you need to install this middleware `scrapy-zyte-smartproxy`. 

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

pip install scrapy-zyte-smartproxy

pip install scrapy-zyte-smartproxy

How to set up a proxy using Requests?

First, import the Requests library, then create a proxy dictionary to map the protocols - HTTP and HTTPS to a proxy URL. Finally, set up a response using requests.get method to make the request to a URL using the proxy dictionary. For example:

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

import requests

proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080', }

response = requests.get('http://example.org', proxies=proxies)

import requests proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080', } response = requests.get('http://example.org', proxies=proxies)

Configure proxies for individual URLs

You can configure proxies for individual URLs even if the schema is the same. This comes in handy when you want to use different proxies for different websites you wish to scrape.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

import requests

proxies = { 'http://example.org': 'http://10.10.1.10:3128', 'http://something.test': 'http://10.10.1.10:1080', }

requests.get('http://something.test/some/url', proxies=proxies)

import requests proxies = { 'http://example.org': 'http://10.10.1.10:3128', 'http://something.test': 'http://10.10.1.10:1080', } requests.get('http://something.test/some/url', proxies=proxies)

Creating sessions

Sometimes you need to create a session and use a proxy at the same time to request a page. In this case, you first have to create a new session object and add proxies to it then finally send the request through the session object:

 `requests.get` essentially uses the `requests.Session` under the hood.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

import requests

s = requests.Session()

s.proxies = {

"http": "http://10.10.10.10:8000",

"https": "http://10.10.10.10:8000",

}

r = s.get("http://toscrape.com")

import requests s = requests.Session() s.proxies = { "http": "http://10.10.10.10:8000", "https": "http://10.10.10.10:8000", } r = s.get("http://toscrape.com")

How to rotate proxies?

For the internet, your IP address is your identity. One can only make limited requests to a website with one IP. Think of websites as some sort of regulator. Websites get suspicious of requests coming from the same IP over and over again. This is ‘IP Rate Limitation’. IP rate limitations applied by websites can cause blocking, throttling, or CAPTCHAs. One way to overcome this is to rotate proxies. Read more about why you need rotating proxies.

Now let's get to the “how” part. This tutorial demonstrates three ways you work with rotating proxies:

  1. Writing a rotating proxies logic using the Request library
  2. Rotating proxies in python using the Scrapy middleware scrapy-rotating-proxies 
  3. Using Zyte Smart Proxy Manager

 

Note: You don’t need any different proxies to run the code demonstrated in this tutorial. If your product/service relies on web scraped data, a free proxy solution will probably not be enough for your needs. 

Let’s discuss them one by one:

Rotating proxies using Request library

In the code shown below, first, we create a proxy pool dictionary. Then, randomly pick a proxy to use for our request. If the proxy works properly we can access the given site. If there’s a connection error we may have to delete this proxy from the list and retry the same URL with another proxy.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

import requests

s = requests.Session()

s.proxies = {

"http": "http://10.10.10.10:8000",

"https": "http://10.10.10.10:8000",

}

r = s.get("http://toscrape.com")

import requests s = requests.Session() s.proxies = { "http": "http://10.10.10.10:8000", "https": "http://10.10.10.10:8000", } r = s.get("http://toscrape.com")

Rotating proxies in python using Scrapy

In your settings.py

  1.  add the list of proxies like this.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

ROTATING_PROXY_LIST = [

'Proxy_IP:port',

'Proxy_IP:port',

# ...

]

ROTATING_PROXY_LIST = [ 'Proxy_IP:port', 'Proxy_IP:port', # ... ]

If you want more external control over the IPs, you can even load it from a file like this.

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

ROTATING_PROXY_LIST_PATH = 'listofproxies.txt'

ROTATING_PROXY_LIST_PATH = 'listofproxies.txt'

  1. Enable the middleware

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

DOWNLOADER_MIDDLEWARES = {

# ...

'rotating_proxies.middlewares.RotatingProxyMiddleware': 800,

'rotating_proxies.middlewares.BanDetectionMiddleware': 800,

# ...

}

DOWNLOADER_MIDDLEWARES = { # ... 'rotating_proxies.middlewares.RotatingProxyMiddleware': 800, 'rotating_proxies.middlewares.BanDetectionMiddleware': 800, # ... }

That’s it! Now all your requests will automatically be routed randomly between the proxies.

Note: Sometimes the proxy that you are trying to use is just simply banned. In this case, there’s not much you can do about it other than remove it from the pool and retry using another proxy. But other times if it isn’t banned you just have to wait a little bit before using the same proxy again.

Use Zyte Smart Proxy Manager

The above-discussed ways to rotate proxies work well for building demos and minimum viable products. But things can get tricky as soon as you decide to scale your data extraction project. Infrastructure management of proxy pools is quite challenging, time-consuming, and resource extensive. You will soon find yourself refurbishing proxies to keep the pool healthy, managing bans and sessions, rotating user agents, etc. Proxy infrastructure also needs to be configured to work with headless browsers to crawl javascript-heavy websites. Phew! It’s not shocking how quickly your data extraction project gets converted into a proxy management project.

Thanks to the Zyte Smart Proxy Manager – you don't need to rotate and manage any proxies. It is all done automatically so you can focus on extracting quality data. Let’s see how easy it is to integrate with your scrapy project. 

  1. In the settings file of your Scrapy project, enable the middleware

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

# enable the middleware

DOWNLOADER_MIDDLEWARE={'scrapy_zyte_smartproxy.ZyteSmartProxyMiddleware': 610}

# enable the middleware DOWNLOADER_MIDDLEWARE={'scrapy_zyte_smartproxy.ZyteSmartProxyMiddleware': 610}

  1. In your Scrapy spider, add these attributes

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

# enable Zyte Proxy

ZYTE_SMARTPROXY_ENABLED = True

# the API key you get with your subscription

ZYTE_SMARTPROXY_APIKEY = '<your_zyte_proxy_apikey>'

# enable Zyte Proxy ZYTE_SMARTPROXY_ENABLED = True # the API key you get with your subscription ZYTE_SMARTPROXY_APIKEY = '<your_zyte_proxy_apikey>'

Demo code for the above-discussed settings,

Plain text

Copy to clipboard

Open code in new window

EnlighterJS 3 Syntax Highlighter

import scrapy

class QuotesSpider(scrapy.Spider):

name = "quotes"

zyte_smartproxy_enabled = True

zyte_smartproxy_apikey = 'a7f74201a57542d7a0b0a08946147fd3'

custom_settings = {

"DEFAULT_REQUEST_HEADERS": {

"X-Crawlera-Profile": "desktop",

"X-Crawlera-Cookies": "disable",

}

}

def start_requests(self):

urls = [

'https://quotes.toscrape.com/page/1/',

'https://quotes.toscrape.com/page/2/',

]

for url in urls:

yield scrapy.Request(url=url, callback=self.parse)

def parse(self, response):

page = response.url.split("/")[-2]

filename = f'quotes-{page}.html'

with open(filename, 'wb') as f:

f.write(response.body)

self.log(f'Saved file {filename}')

import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" zyte_smartproxy_enabled = True zyte_smartproxy_apikey = 'a7f74201a57542d7a0b0a08946147fd3' custom_settings = { "DEFAULT_REQUEST_HEADERS": { "X-Crawlera-Profile": "desktop", "X-Crawlera-Cookies": "disable", } } def start_requests(self): urls = [ 'https://quotes.toscrape.com/page/1/', 'https://quotes.toscrape.com/page/2/', ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): page = response.url.split("/")[-2] filename = f'quotes-{page}.html' with open(filename, 'wb') as f: f.write(response.body) self.log(f'Saved file {filename}')

This piece of code sends a successful HTTP Python request to https://quotes.toscrape.com/. 

When you use Zyte Proxy Manager, you don’t need to deal with proxy rotation manually. Everything is taken care of internally through the use of our rotating proxies.

You can try Zyte Smart Proxy Manager for 14 days for free.

Try Zyte API

Build your first scraper in minutes

Free trial, no credit card. From a single request to production in an afternoon.

Get started
Proxies
N

Neha Setia Nagpal

More from this author

In this article

  • In this developer guide, you will learn how to:
  • Prerequisites
  • How to set up a proxy using Requests?
  • Configure proxies for individual URLs
  • Creating sessions
  • How to rotate proxies?
  • Rotating proxies using Request library
  • Rotating proxies in python using Scrapy
  • Use Zyte Smart Proxy Manager

Follow

Get the latest

Zyte and the data web in your inbox — or wherever you already are.

Subscribe

Or follow elsewhere

The Community · Newsletter

The best of Zyte and the data web, in your inbox.

One curated edition — new articles, product updates, and the stories shaping the data web. No noise.

G2.com

Capterra.com

Proxyway.com

EWDCI logoMost loved workplace certificateZyte rewardISO 27001 iconG2 rewardG2 rewardG2 reward

© Zyte Group Limited 2026
1python -m pip install requests
Copy
1pip install scrapypip install scrapy-rotating-proxies
Copy
1pip install scrapy-zyte-smartproxy
Copy
1import requests 
2proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080', }
3response = requests.get('http://example.org', proxies=proxies)
Copy
1import requests 
2proxies = { 'http://example.org': 'http://10.10.1.10:3128', 'http://something.test': 'http://10.10.1.10:1080', }
3requests.get('http://something.test/some/url', proxies=proxies)
Copy
1import requests
2s = requests.Session()
3s.proxies = {
4  "http": "http://10.10.10.10:8000",
5  "https": "http://10.10.10.10:8000",
6}
7r = s.get("http://toscrape.com")
Copy
1import requests
2s = requests.Session()
3s.proxies = {
4  "http": "http://10.10.10.10:8000",
5  "https": "http://10.10.10.10:8000",
6}
7r = s.get("http://toscrape.com")
Copy
1ROTATING\_PROXY\_LIST = \[
2  'Proxy\_IP:port',
3  'Proxy\_IP:port',
4  # ...
5\]
Copy
1ROTATING\_PROXY\_LIST\_PATH = 'listofproxies.txt'
Copy
1DOWNLOADER\_MIDDLEWARES = {
2  # ...
3  'rotating\_proxies.middlewares.RotatingProxyMiddleware': 800,
4  'rotating\_proxies.middlewares.BanDetectionMiddleware': 800,
5  # ...
6}
Copy
1\# enable the middleware
2DOWNLOADER\_MIDDLEWARE={'scrapy\_zyte\_smartproxy.ZyteSmartProxyMiddleware': 610}
Copy
1\# enable Zyte Proxy
2ZYTE\_SMARTPROXY\_ENABLED = True
3
4# the API key you get with your subscription
5ZYTE\_SMARTPROXY\_APIKEY = '<your\_zyte\_proxy\_apikey>'
Copy
1import scrapy
2
3
4class QuotesSpider(scrapy.Spider):
5  name = "quotes"
6  zyte\_smartproxy\_enabled = True
7  zyte\_smartproxy\_apikey = 'a7f74201a57542d7a0b0a08946147fd3'
8  custom\_settings = {
9      "DEFAULT\_REQUEST\_HEADERS": {
10          "X-Crawlera-Profile": "desktop",
11          "X-Crawlera-Cookies": "disable",
12      }
13  }
14
15  def start\_requests(self):
16      urls = \[
17          'https://quotes.toscrape.com/page/1/',
18          'https://quotes.toscrape.com/page/2/',
19      \]
20      for url in urls:
21          yield scrapy.Request(url=url, callback=self.parse)
22
23  def parse(self, response):
24      page = response.url.split("/")\[-2\]
25      filename = f'quotes-{page}.html'
26      with open(filename, 'wb') as f:
27          f.write(response.body)
28      self.log(f'Saved file {filename}')
Copy