Logo
Proxy 101
May 22, 2026
6 min

Python Request Proxy Guide: Use Proxies Safely In Requests

Alex Sadovskij
Alex Sadovskij
CEO Proxy-Cheap
Python Request Proxy Guide: Use Proxies Safely In Requests
Summary
Learn how to use proxies with Python Requests, including HTTP, HTTPS, SOCKS5, authentication, sessions, proxy rotation, and fixing common proxy errors.

You use a proxy with Python Requests by passing a proxies dictionary to your request and putting your proxy address in it, for example proxies={"http": "http://user:pass@host:port", "https": "http://user:pass@host:port"}.

What this guide covers

In this guide you will learn:

What a proxy is and how it works with Python Requests

  • How to add a proxy to a single requests.get or requests.post call
  • How to use HTTP, HTTPS, and SOCKS proxies
  • How to add username and password authentication
  • How to manage sessions and cookies through a proxy
  • How to rotate IPs for scraping at scale
  • How to fix common proxy errors in Python
  • How to use the same proxy setup across Requests, curl, wget, and Selenium
  • How to choose the right proxy type for your project

By the end, you will be able to plug a proxy into almost any Python Requests script in a safe and stable way.

What is a proxy and how does it work with Python Requests

A proxy is a server that sits between your code and the site you call. Your Python script talks to the proxy. The proxy then talks to the target site. The proxy server acts as an intermediary between your code and the target website, routing your web requests and hiding your real IP address. The site does not see your real IP address; instead, it sees the proxy IP address. The proxy masks your real IP address and replaces it with the proxy IP address, so your actual IP address is not exposed to the target site.

If you are new to proxies, it can help to read a simple overview of what proxies are. In short, a proxy changes how your traffic looks from the outside by altering the IP address that websites see.

When you send a request with Python Requests, you usually connect directly to the target domain using your own IP address. When you use a proxy, Requests connects to the proxy IP address instead. The proxy then forwards your HTTP request for you. Many proxies can also hide your real IP address and some headers. This is called an anonymous proxy server.

Using a proxy with Requests gives you several benefits:

  • You can access sites from another country or region.
  • You can reduce the chance of blocks when scraping.
  • You can keep your real IP private.
  • You can route traffic for many scripts through a single exit point.

All of this is controlled by a small proxies dictionary in your code.

Quick start: simple Python Request proxy example

Before running the example below, make sure to install the Python Requests library using pip:

pip install requests

Here is the smallest working example of using a proxy with Python Requests:

import requests proxies = {    "http": "http://user:password@proxy_host:proxy_port",    "https": "http://user:password@proxy_host:proxy_port", } response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10) print(response.json())

This script does the following:

  1. Imports the requests module, which is required for making HTTP requests through proxies.
  2. Defines a proxies dictionary with HTTP and HTTPS keys.
  3. Uses the full proxy URL including scheme, username, password, host, and port.
  4. Calls requests.get with the proxies argument.
  5. Prints the IP that the site sees.

If the output IP is different from your real IP, the proxy works.

The example above also shows the basic pattern that people search for as a “python proxy requests” snippet. Almost every proxy setup with Requests builds on this pattern.

Proxy URL format explained

The proxy URL has a clear format:

scheme://username:password@host:port

Each part means:

  • scheme - http, https, or socks5 for most use cases.
  • username:password - your login details for the proxy, used for proxy authentication when the proxy requires credentials.
  • host - the proxy server address, often a domain. This, along with the port, is key proxy server information needed to connect.
  • port - the port number the proxy listens on.

Some proxies do not need a username and password. In that case you can drop that part:

http://proxy_host:proxy_port

Always use the scheme your proxy provider gives you. If they say it is a SOCKS5 proxy, use socks5:// or socks5h:// in your proxy URL.

Correct proxy configuration is essential for successful connections.

HTTP and HTTPS proxies in Python Requests

Most HTTP proxies work with the basic proxies dictionary. Specifying the 'https' key in the proxies dictionary ensures that HTTPS protocols and HTTPS traffic are routed through the proxy, allowing secure connections.

import requests proxies = {    "http": "http://user:password@proxy_host:proxy_port",    "https": "http://user:password@proxy_host:proxy_port", } url = "https://example.com" response = requests.get(url, proxies=proxies, timeout=10) print(response.status_code)

When using requests.get, the proxies parameter is used to specify the proxy server details for both HTTP and HTTPS requests. Configuring proxies for HTTPS requests is important for secure data transfer, as it ensures that HTTPS traffic is properly routed through the proxy using HTTPS protocols.

Some tips for HTTP and HTTPS proxies:

  • Use the same proxy URL for both http and https keys unless your provider tells you to separate them.
  • Always set a timeout. Proxies can fail or be slow.
  • Check response.status_code to detect blocks.

If your proxy is only for HTTP and not HTTPS, you can set only the http key. Requests will then use your normal connection for HTTPS.

SOCKS proxies in Python Requests

SOCKS proxies work at a lower level. They can handle more types of traffic, including different types of web requests, making them suitable for a variety of network tasks. To use them in Requests you need extra support.

First, install the extra package:

pip install "requests[socks]"

Then you can use a SOCKS proxy like this:

import requests proxies = {    "http": "socks5h://user:password@proxy_host:proxy_port",    "https": "socks5h://user:password@proxy_host:proxy_port", } response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10) print(response.json())

The socks5h scheme tells Requests to resolve DNS through the proxy. This can help if the site blocks your DNS requests.

Proxies with username and password

Most paid proxies require proxy authentication, meaning you must include your username and password in the proxy URL to access an authenticated proxy. With Python Requests, you typically provide the login details in the proxy URL as shown before. This is essential for proxies that require authentication.

proxies = {    "http": "http://user123:strongpassword@proxy_host:proxy_port",    "https": "http://user123:strongpassword@proxy_host:proxy_port", }

If your proxy uses IP whitelisting instead of username and password, then your code does not need to include credentials. The proxy will accept connections from your machine IP directly.

Some proxies rotate credentials or limit how long they are valid. If you encounter authentication errors (such as HTTP 407), it often means the proxy requires authentication and your credentials may be incorrect or expired. Always check that your username and password are up to date on your provider dashboard when using an authenticated proxy.

Using environment variables for proxy settings

You can also configure proxies for Requests through environment variables. This can be useful in scripts that run on servers or in containers.

Requests understands these environment variables and relies on them to manage proxy configurations:

  • HTTP_PROXY
  • HTTPS_PROXY
  • NO_PROXY

For example, setting these environment variables allows Requests to handle proxies automatically, including excluding certain hosts from using the proxy with NO_PROXY:

export HTTP_PROXY="http://user:password@proxy_host:proxy_port" export HTTPS_PROXY="http://user:password@proxy_host:proxy_port" export NO_PROXY="localhost,127.0.0.1"

Then you can use Requests without passing a proxies dictionary (proxies dict) in your code:

import requests response = requests.get("https://httpbin.org/ip", timeout=10) print(response.json())

Requests will read the proxy from the environment. This keeps your code clean and makes it easy to change the proxy without editing the script. Configuring proxies with Python Requests can be done either through environment variables as shown above, or by passing a proxies dictionary directly, depending on your use case for proxies with Python requests.

Using Session objects with proxies

For larger projects it is better to use a Session object. A session lets you efficiently handle multiple requests while reusing the same TCP connection, cookies, and headers across many requests. By maintaining a persistent TCP connection, you improve performance and simplify managing authentication and cookies, especially when making multiple requests to the same server.

You can attach a proxy to the session like this:

import requests session = requests.Session() session.proxies.update({    "http": "http://user:password@proxy_host:proxy_port",    "https": "http://user:password@proxy_host:proxy_port", }) session.headers.update({    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" }) for page in range(1, 6):    url = f"https://example.com/list?page={page}"    response = session.get(url, timeout=10)    print(page, response.status_code)

This approach is useful when scraping many pages from the same site. The proxy settings apply to every request made with that session, and the session will reuse the same TCP connection for better efficiency.

You can also override the proxy for a single request by passing proxies to that call. The per request proxies will take priority over the session level proxies.

Rotating proxies and IP addresses

When using Python Requests for web scraping, proxy rotation and using multiple proxies are key strategies to distribute requests, avoid detection, and bypass rate limits. By rotating through multiple IP addresses, you can reduce the risk of being blocked or throttled, especially when making numerous requests or accessing region-locked content.

There are two common ways to achieve proxy rotation and manage multiple IP addresses with Python Requests:

  1. Use a backconnect proxy endpoint that automatically rotates IPs for you.
  2. Rotate through a list of proxy servers (multiple proxies) in your code to distribute requests across different IP addresses.

For a deeper walkthrough of both methods you can follow this detailed guide for IP rotation in Python.

Here is a simple example that rotates through a list of proxies in code to distribute requests and avoid sending all traffic from a single IP:

import itertools import requests proxies_list = [    "http://user:pass@proxy1:8000",    "http://user:pass@proxy2:8000",    "http://user:pass@proxy3:8000", ] proxy_cycle = itertools.cycle(proxies_list) urls = [    "https://httpbin.org/ip",    "https://example.com",    "https://httpbin.org/headers", ] for url in urls:    proxy = next(proxy_cycle)    proxies = {"http": proxy, "https": proxy}    try:        response = requests.get(url, proxies=proxies, timeout=10)        print(url, response.status_code)    except requests.RequestException as exc:        print(url, "failed with", exc)

For handling numerous requests or large-scale scraping projects, premium proxies are recommended. Premium proxies offer better reliability, automatic proxy rotation, geolocation targeting, and higher success rates compared to free options.

In real scraping setups you will also add random delays, random headers, and smarter retry logic. The important part is that you do not send hundreds of calls from a single IP in a short time.

Handling common proxy errors in Python Requests

When working with proxies it is normal to see some errors. Robust error handling is essential for managing proxy failures and maintaining reliable scripts. The key is to handle them in code and know when the problem is in your script, in the proxy, or on the target site.

Common problems include:

  • requests.exceptions.ProxyError - often means the proxy is down, wrong, or the proxy format is incorrect, leading to connection errors.
  • requests.exceptions.ConnectTimeout - the proxy or target is too slow or unreachable.
  • HTTP status codes like 403 or 429 - the target site is blocking or limiting you. HTTP 429 specifically indicates too many requests, meaning you've hit a rate limit and should consider proxy rotation or slowing down your requests.

To understand why these happen, it can help to read more about what a proxy error is.

Here is a robust pattern to wrap your request in retries and handle basic proxy issues with proper error handling:

import time import requests proxies = {    "http": "http://user:password@proxy_host:proxy_port",    "https": "http://user:password@proxy_host:proxy_port", } url = "https://example.com" max_retries = 3 for attempt in range(1, max_retries + 1):    try:        response = requests.get(url, proxies=proxies, timeout=10)        if response.status_code in (403, 429):            print("Blocked or rate limited, status:", response.status_code)            # 429 means too many requests; consider rotating proxies or reducing request frequency            time.sleep(5)            continue        response.raise_for_status()        print("Success on attempt", attempt)        break    except requests.exceptions.ProxyError as exc:        print("Proxy error on attempt", attempt, exc)        time.sleep(2)    except requests.exceptions.RequestException as exc:        print("Request failed on attempt", attempt, exc)        time.sleep(2)

This example:

  • Retries a few times before giving up.
  • Waits between attempts.
  • Handles proxy specific errors and connection errors.
  • Checks for common block status codes, including handling too many requests (HTTP 429).
  • Demonstrates basic error handling for reliable proxy usage.

In a production script you might also log failures and switch to a new proxy after a number of errors.

Using proxies across Requests, curl, and wget

Most teams do not use only Python. You might debug with curl or use wget in a cron job. It is best if your proxy setup is similar across tools. Selecting the right proxy proxies is important for consistent performance, reliability, and security across different tools like Requests, curl, and wget.

For curl, you can follow this guide on how to use curl with a proxy. The same proxy URL you use in Requests will usually work with curl.

If you also automate downloads from the command line, you can keep settings aligned by reading about wget with proxy. Using the same proxy details in all tools makes debugging much easier.

Once you confirm that the proxy works in curl or wget, you can plug the same URL into your Python Requests proxies dictionary with more confidence.

Using proxies with Selenium and Requests together

Many browser automation flows use both Selenium and Requests in the same project. For example, you might log in with Selenium and then scrape data with Requests using the same proxy.

To set this up, first make sure your browser automation uses a proxy. You can follow a detailed Selenium proxy server guide for this part.

Then, in your Python code, reuse the same proxy URL for Requests:

proxy_url = "http://user:password@proxy_host:proxy_port" selenium_proxy = proxy_url  # used in your Selenium options requests_proxies = {    "http": proxy_url,    "https": proxy_url, }

Consistent proxy configuration across both Selenium and Requests helps maintain anonymity and avoid detection. With this approach your real IP stays hidden for both browser and raw HTTP calls. It also keeps your network behavior consistent across tools, which helps avoid detection.

Choosing the right proxy type for Python Requests

Different projects need different proxy types. Here are some common types and when they fit Requests based workflows.

  • Datacenter proxies: Good for speed and cost. Often used for scraping sites that do not block aggressively.
  • Residential proxies: Use IPs from real devices and networks. Better for harder targets but usually slower and more expensive.
  • Mobile proxies: Use IPs from mobile carriers. Useful when sites trust mobile users more.
  • Free proxies: These are readily available and can be used for basic tasks or testing, but they are often unreliable, slow, and lack features like rotation and geolocation. Free proxies are not recommended for serious or large-scale scraping projects.

If you work with strict sites or need your traffic to look like normal user traffic, residential proxies are usually the safest choice. They pair well with Python Requests because you can rotate IPs and spread load across many real residential connections.

When choosing a proxy provider, prioritize reliable proxies to ensure your requests succeed, maintain data security, and avoid detection or blocking during web scraping or data collection.

Think about:

  • How many requests you plan to send per hour.
  • How sensitive the target site is.
  • How much you value stability over cost.

Your answers will guide the proxy type and rotation strategy.

Proxy performance: speed, latency, and reliability considerations

When working with proxies in your Python Requests scripts, the performance of your proxy server can make or break your web scraping tasks. Speed, latency, and reliability are critical factors that directly impact how efficiently you can collect data, avoid IP bans, and maintain stable connections.

Security, logging, and ethics

When you send traffic through a proxy, that proxy can see your requests. Treat your proxy like any other part of your infrastructure and follow security best practices.

Basic guidelines:

  • Never send passwords or private tokens through a proxy you do not trust.
  • Use HTTPS whenever possible so data between proxy and target stays encrypted.
  • Store proxy credentials in environment variables or secret managers, not in plain source code.
  • Log responses carefully and avoid storing sensitive data in plain text.

Also, use proxies in an ethical way:

  • Respect target site terms of service.
  • Obey local laws in your country and the server country.
  • Limit request rates so you do not harm the site.
  • Honor robots.txt where it applies to your use case.

Proxies and Python Requests are powerful tools. Use them responsibly so your projects stay safe and sustainable.

When to scale up your proxy setup

At first, a single proxy in a simple proxies dictionary may be enough. Over time, you may notice more blocks, more captchas, or more timeouts. This is a sign that your proxy and request logic should grow with your project.

You might need to:

  • Add a pool of proxies and rotate them. When managing a pool, it's important to keep track of proxy server information such as IP address, port, and credentials to ensure effective proxy management and troubleshooting.
  • Add smarter retry logic based on status codes.
  • Spread traffic across time with queues and schedulers.
  • Add health checks for your proxies.

Python Requests gives you a simple API that still works well as you scale. You can wrap it in your own helper functions, control concurrency with threads or async wrappers, and plug it into larger scraping or automation systems.

Start using stable proxies in your Python scripts

If you want stable, easy to use proxies for your Python Requests scripts, python's requests library makes it easy to integrate proxies into your scripts. The requests library is widely used for automating web interactions and managing proxy settings, making it a popular choice for web scraping and bypassing IP blocks. It helps to use a provider that gives clear proxy formats, strong uptime, and a simple dashboard. You can start today by creating an account at Proxy-Cheap and connecting one of their endpoints to the proxies dictionary examples shown in this guide.

Frequently Asked Questions

Pass a proxies dictionary to the call: proxies = { "http": "http://user:password@proxy_host:proxy_port", "https": "http://user:password@proxy_host:proxy_port", } response = requests.get("https://example.com", proxies=proxies, timeout=10) This affects only that specific request.

Create a Session and update its proxy settings: session = requests.Session() session.proxies.update({ "http": "http://user:password@proxy_host:proxy_port", "https": "http://user:password@proxy_host:proxy_port", }) response = session.get("https://example.com", timeout=10) All calls made with session will use that proxy.

Yes. The proxy URL format is usually the same. You can follow guides for curl and wget and reuse the same proxy details in your Python proxies dictionary. That way you debug in one tool and then copy settings to the others with less guesswork.

Common reasons include: The proxy host or port is wrong. The username or password is wrong or expired. Your IP is not allowed to connect to the proxy. The proxy is down or overloaded. Check the proxy URL, confirm your credentials in the provider dashboard, and test the proxy with curl or a browser extension. If it works there but not in Requests, review your proxies dictionary and timeout settings.