Notes on networking and developer tooling
Proxy Setup
4 min read

pip and Python requests Behind an HTTP or SOCKS5 Proxy

pip takes --proxy, PIP_PROXY, HTTPS_PROXY or a proxy line in pip.conf. requests takes a proxies dict per call, and SOCKS5 needs the PySocks extra. The https entry in the dict is still an http:// proxy URL for an HTTP proxy.

Editorial team

pip accepts --proxy, the PIP_PROXY variable, the standard HTTPS_PROXY variable, or a proxy line in its config file. The requests library takes a proxies dictionary on each call. SOCKS5 works in both once PySocks is installed. This article reflects the tools as of November 2026 and uses placeholder proxy addresses throughout.

How do I make pip use a proxy?

The quickest way is the --proxy option, which takes a URL in the form scheme://[user:password@]host:port. For something permanent, write it into pip's configuration with pip config; for something temporary, export an environment variable.

python -m pip install --proxy http://user:password@proxy.example.com:8080 requests

# permanent, in the user config file
python -m pip config set global.proxy http://proxy.example.com:8080
python -m pip config list
python -m pip config unset global.proxy

# environment variables
export HTTPS_PROXY=http://proxy.example.com:8080
export PIP_PROXY=http://proxy.example.com:8080

Running python -m pip instead of bare pip ensures that you configure the same interpreter you will install into, which matters when several Pythons or virtual environments coexist. Use python -m pip config debug to see which config files pip reads. Proxy URL syntax and percent-encoding of special characters in a password work as described in setting a proxy for git, and the key names for JavaScript tools are in npm, pnpm and Yarn proxy settings.

How do I pass a proxy to Python requests?

Give requests a dictionary that maps a URL scheme to a proxy URL. For an HTTP proxy, both entries are http:// URLs: the https key names the scheme of the target, not the scheme of the proxy, and requests opens a CONNECT tunnel through the proxy for HTTPS targets.

import requests

proxy = "http://user:password@proxy.example.com:8080"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://api.ipify.org", proxies=proxies, timeout=10)
print(r.text)

Always pass a timeout; without one, requests can wait indefinitely. If the password contains reserved characters, encode it first:

from urllib.parse import quote

password = quote("p@ss/word", safe="")
proxy = "http://user:" + password + "@proxy.example.com:8080"

Do environment variables or my code win?

With the default trust_env=True, requests also reads HTTP_PROXY, HTTPS_PROXY, ALL_PROXY and NO_PROXY, and it can read a .netrc file. The requests documentation warns that values set on Session.proxies may be overridden by environment proxies. The reliable fix is to pass proxies= on every call, or to set trust_env to False when you want the environment ignored completely.

s = requests.Session()
s.trust_env = False
r = s.get("https://api.ipify.org", proxies=proxies, timeout=10)

How do I use a SOCKS5 proxy with pip and requests?

Install PySocks, then use a socks5:// or socks5h:// URL. With socks5h the proxy resolves hostnames, so local DNS is not involved; plain socks5 resolves them on your machine first. For requests, the supported way to get PySocks is the extra.

python -m pip install "requests[socks]"

proxy = "socks5h://user:password@proxy.example.com:1080"
proxies = {"http": proxy, "https": proxy}

pip needs PySocks too, installed into the same interpreter that runs pip. If pip reports "Missing dependencies for SOCKS support", install it first without the SOCKS proxy, or through an HTTP proxy, and then switch: python -m pip install pysocks. Note that SOCKS5 here means TCP connections; UDP traffic over SOCKS5 is a separate feature that these libraries do not use for HTTP.

What do the common errors mean?

requests wraps most network failures in its own exception types, and pip prints the underlying message. Reading the exact text narrows the cause quickly, because each one points at a different layer: the proxy, the credentials, TLS, or the target.

MessageLayerWhat to check
ProxyError: Cannot connect to proxyProxy connectionHost, port and scheme; firewall
407 Proxy Authentication RequiredCredentialsUsername, password, percent-encoding
Missing dependencies for SOCKS supportLocal environmentInstall PySocks in the same interpreter
SSLError: certificate verify failedTLSA TLS-inspecting proxy; supply its CA, do not disable verification
ConnectTimeout / ReadTimeoutNetwork path or slow targetTest with curl through the same proxy

How can I confirm the script really uses the proxy?

Compare the address a public echo service sees with and without the proxy. Two different values mean the proxy is in use. Building the helper around a session with trust_env disabled keeps leftover environment variables from skewing the comparison, and catching the specific exceptions tells you which layer failed.

import requests
from requests.exceptions import ProxyError, ConnectTimeout, ReadTimeout

proxy = "http://user:password@proxy.example.com:8080"
proxies = {"http": proxy, "https": proxy}

def seen_ip(proxies=None):
    s = requests.Session()
    s.trust_env = False
    return s.get("https://api.ipify.org", proxies=proxies, timeout=10).text

print("direct:", seen_ip())
try:
    print("proxy: ", seen_ip(proxies))
except ProxyError as e:
    print("proxy or credentials problem:", e)
except (ConnectTimeout, ReadTimeout) as e:
    print("timeout:", e)

The same check from the shell is curl -x http://proxy.example.com:8080 https://api.ipify.org. If curl and Python disagree, look at environment variables, trust_env and which interpreter is running the script.

Where AnboVPN fits

AnboVPN's HTTP/SOCKS5 proxy offers both an HTTP port (including HTTPS tunnels) and a SOCKS5 port behind one username and password, so every example above can use the same credentials. SOCKS5 UDP is not supported, which does not affect pip or requests. If you add your machine to the source-IP allowlist, scripts no longer need a password in code or config. Traffic counts against your data plan. See the HTTP/SOCKS5 proxy page.

References

pip
python
requests
SOCKS5
proxy

FAQ

Why is the https entry in the requests proxies dict an http:// URL?
The dictionary key is the scheme of the website you are requesting, and the value is the address of the proxy. An ordinary HTTP proxy accepts a CONNECT request from the client and then tunnels the encrypted HTTPS traffic, so the proxy URL itself still starts with http://. Only use https:// there if the proxy itself is reached over TLS.
Does pip honor NO_PROXY?
Yes, because pip builds on the requests library, it reads the same proxy environment variables, including NO_PROXY, as long as no explicit proxy overrides them. Use NO_PROXY for hosts such as a private package index on your internal network that should be reached directly.
How do I use the same proxy for pip and a script without writing the password twice?
Export HTTPS_PROXY and HTTP_PROXY once in the shell or CI job. pip reads them, and a script that uses requests with the default trust_env behavior reads them too, so neither needs the credentials in its own file. Alternatively, use a proxy that authorizes by source IP and skip the password.
Do I need a different tool for SOCKS5 UDP?
pip and requests only make HTTP requests over TCP, so they never need SOCKS5 UDP. It matters for other software such as some games or QUIC-based clients. Check whether your proxy supports it before planning around it.
Ad
  • Dynamic, residential and ISP residential IPs
  • Unlimited devices on one account
  • Smart routing and TUN mode
Free data on sign-up

Back to all posts

Back to all posts

Related posts

Proxy Setup

Git Proxy Setup: Configure http.proxy and Fix Slow Clones

Git over HTTPS reads http.proxy (or the https_proxy variable) and accepts http://, socks5:// and socks5h:// URLs. Git over SSH ignores both and needs ProxyCommand. A slow clone is easiest to diagnose with GIT_CURL_VERBOSE.

git
proxy
SOCKS5