How to Use Proxies with Python Httpx?

If you're doing any amount of web scraping or automated HTTP requests, chances are you'll need to use proxies at some point. Proxies are a necessary tool for bypassing blocks, scaling requests, and enabling anonymous scraping.

In this comprehensive guide, you'll learn how proxies work, why they're useful for web scraping, how to integrate proxies into Python's httpx client, and some best practices for maximizing your proxy ROI.

Why Use Proxies for Web Scraping?

Here are some of the main reasons why you should use proxies with your Python web scrapers and crawlers:

  • Avoid blocking – Many websites block and blacklist IPs that send too many requests. Proxies allow you to rotate different IP addresses, avoiding getting blocked.
  • Bypass geographic restrictions – Some websites restrict content based on location. Proxies let you appear from different countries and access geo-restricted content.
  • Scale requests – Running all your requests from a single IP is slow. Proxies allow you to scale and parallelize requests from multiple IPs.
  • Hide identity – Scraping anonymously is important if you want to avoid detection. Proxies enable scraping without revealing your scraper's real IP.
  • Debug requests – Testing from different IPs helps debug scraping issues and test server side behavior.Reduce costs – Proxy providers allow more flexible and affordable IP rotation than scaling up servers/datacenter IPs.

In short, proxies help you scrape optimally, at scale, and avoid common issues like blocking.

Httpx Proxy Support

The httpx Python package supports both HTTP and SOCKS5 proxies out of the box. To use a proxy, simply pass the proxies into a httpx.Client() or httpx.AsyncClient():

import httpx

proxies = {
  'http://': 'http://user:[email protected]:5678',
  'https://': 'http://user:[email protected]:5678'  

with httpx.Client(proxies=proxies) as client:
  r = client.get('')

This will route all requests through the proxy server on port 5678, authenticating with the provided username and password. You can also set proxies exclusively for specific domains:

proxies = {
   '': '' 

This routes only requests via the proxy, leaving other domains to connect directly. In addition to passing proxies directly, httpx also supports the conventional HTTP_PROXY, HTTPS_PROXY, ALL_PROXY environment variables.

Choosing Proxy Providers

To leverage proxies in your httpx scrapers, you'll need access to a pool of rotating proxy servers.

While you can run your own proxies, commercial proxy providers usually offer the best quality, performance, and anonymity. Some good options:

  • BrightData – The leading proxy provider, offering 72M+ fresh residential IPs with high-performance support. Plans start at $10/GB.
  • Smartproxy – Offers over 55M residential IPs with a focus on sneaker/retail proxies. Plans from $14/month.
  • Soax – Specializes in geo-targeting proxies for accessing locally restricted content. Plans from $99/15 GB.
  • Proxy-Seller – Budget residential proxy provider with and start at $10/GB.

I generally recommend BrightData or Smartproxy for most large-scale scraping use cases. Both offer reliable, high-quality proxies to handle heavy workloads. For more specific use cases like sneaker bots, Soax's geo-targeting, or Smartproxy's retail/sneaker proxies work well. Proxy-Seller is a good budget option that works better for smaller scrapers.

The key things to evaluate are:

  • IP pools – More diverse IPs means better rotation without recycling.
  • Success rate – Percentage of working IPs without issues. Aim for >95%.
  • Locations – Having more geo-distributed IPs allows targeting more sites.
  • Bandwidth – Needed to sustain high requests per second.
  • Features – Rotating IPs, sessions, sticky sessions, etc.
  • Reliability & uptime – Critical for uninterrupted scraping.
  • Support – API, integrations, documentation to ease setup.
  • Cost – Monthly plans & overage pricing.

Rotating Proxies in Python

Now let's look at how to leverage proxies in your Python httpx scripts for effective IP rotation. Rotating proxies means programmatically using a pool of different proxy IPs for each request, rather than reusing the same IPs.

This is crucial for:

  • Avoiding IP based blocks.
  • Scaling requests across multiple IPs in parallel for higher concurrency.
  • Appearing from different geographic locations.

Here is a simple proxy rotation pattern with httpx:

import httpx
from proxies import ProxyPool

proxy_pool = ProxyPool() 

with httpx.Client() as client:
  for url in urls:
    # get next proxy 
    proxy = proxy_pool.get_proxy()  
    # set it for httpx
    proxies = {'http://': proxy, 'https://': proxy}
    client.proxies = proxies
    # make request via rotating proxy
    resp = client.get(url)

We initialize a ProxyPool instance which handles fetching and rotating our list of proxies. Inside the request loop, we call get_proxy() to get the next proxy, set it as the httpx client's proxy, then make the HTTP request through the rotated IP.

This ensures each request uses a different proxy. The key is having a ProxyPool a class that handles:

  • Fetching proxies from your provider's API.
  • Local proxy caching and lifecycle management.
  • Cycling through proxies in a round-robin order.

For example:

class ProxyPool:

  def __init__(self):
    self.proxies = []
    self.currentIndex = 0  
    # load proxies from API
  def load_proxies(self):
    """Fetch proxies from API and add to pool"""
    res = requests.get('')
    proxies = res.json()
  def get_proxy(self):
    """Return next proxy and rotate index"""
    proxy = self.proxies[self.currentIndex]
    self.currentIndex += 1
    if self.currentIndex >= len(self.proxies):
        self.currentIndex = 0
    return proxy

This handles populating the proxy pool, then cycles through it in round-robin order each call to get_proxy(). More advanced implementations can add proxy validation, backfilling new proxies when existing ones fail, IP block detection, etc. But this basic approach allows efficiently rotating IPs with just a few lines of code!

Proxy Authentication

Many proxy services like BrightData or Oxylabs require authenticating to access their proxy pools, via either username/password or API keys. Here is how to handle proxy authentication with httpx:

HTTP Basic Auth

If the proxy uses username + password authentication:

proxy = 'http://user:pass@proxy-server:8080'

Include the username/password in the proxy URL when setting it in httpx:

client.proxies = {
  'http://': proxy,
  'https://': proxy

Httpx will automatically pass the user:pass credentials in the Proxy-Authorization header.

API Keys

For API key authentication, you'll need to manually add the API key header:

api_key = 'abcd1234...'

headers = {
  'Proxy-Authorization': 'Bearer ' + api_key   

client.headers = headers

This sets the API key auth header before making requests through the proxy.

Proxy URLs from Provider

Many proxy services provide authenticated proxy URLs or endpoints:

https://user:[email protected]:22225
https://[email protected]:30000

You can directly pass these pre-authenticated URLs as the httpx proxy:

proxy = 'https://user:[email protected]:1234'

client.proxies = {
  'http://': proxy, 
  'https://': proxy

This is the easiest way to handle authenticated proxies, without needing to deal with headers.

Troubleshooting Proxy Issues

Proxies generally work seamlessly with httpx, but you may occasionally hit issues like:

  • Connection errors – Usually indicate a bad/offline proxy server. Try the request again with a fresh proxy.
  • Authorization errors – Can mean invalid credentials if proxy needs auth. Verify API keys are correct.
  • Blocked IPs – If a proxy IP gets blocked by the target site, rotate to a new IP.
  • Slow proxies – Try refreshing your proxy pool to replace slow proxies.
  • Geo-restrictions – Use proxies specifically for required locations to bypass geo-blocks.
  • Scraper detection – Rotate IPs frequently and use residential proxies to appear more human.
  • Intermittent failures – Have robust retry logic and alternate IPs to handle transient proxy failures.

The key is having sufficient proxy redundancy and IP diversity to mitigate issues by constantly rotating.


Proxies are invaluable for managing scale, stability, and anonymity in Python web scraping. Httpx makes it easy to add both HTTP and SOCKS5 proxies to your client. The key is then having robust proxy rotation logic – cycling through a large, redundant pool of proxies using a provider's API.

With quality proxies and efficient rotation, you can orchestrate distributed scraping jobs to extract large amounts of data reliably at scale. I hope this guide gave you a good overview of how to integrate and leverage proxies within your Python httpx web scraping scripts!

John Rooney

John Rooney

John Watson Rooney, a self-taught Python developer and content creator with a focus on web scraping, APIs, and automation. I love sharing my knowledge and expertise through my YouTube channel, My channel caters to all levels of developers, from beginners looking to get started in web scraping to experienced programmers seeking to advance their skills with modern techniques. I have worked in the e-commerce sector for many years, gaining extensive real-world experience in data handling, API integrations, and project management. I am passionate about teaching others and simplifying complex concepts to make them more accessible to a wider audience. In addition to my YouTube channel, I also maintain a personal website where I share my coding projects and other related content.

We will be happy to hear your thoughts

      Leave a reply

      Compare items
      • Total (0)