Install SOCKS support first
Requests needs the SOCKS extra before socks5:// works. Without it, the proxy line can look correct and still fail before any traffic reaches the proxy.
python -m pip install "requests[socks]"
Use socks5h:// when you want DNS resolution to happen through the proxy. Use socks5:// only when local DNS is acceptable.
import os
import requests
proxy = (
'socks5h://'
f'{os.environ["PROXY_USER"]}:{os.environ["PROXY_PASS"]}'
'@proxynade.net:2555'
)
session = requests.Session()
session.trust_env = False
session.proxies = {
'http': proxy,
'https': proxy,
}
response = session.get('https://example.com', timeout=30)
print(response.status_code)
Use curl before debugging Python
Run one proxy check outside Python. If curl fails, the Python code is not the first problem.
curl -x socks5h://USER:PASS@proxynade.net:2555 https://example.com -I
| Error | Likely cause | Fix |
|---|---|---|
Missing dependencies for SOCKS support | PySocks is not installed | Install requests[socks]. |
407 | Proxy auth failed | Check account, balance, and encoded credentials. |
| DNS leak | Used socks5:// | Use socks5h://. |
| Works in curl, fails in app | Environment proxy override | Set session.trust_env = False. |
Encode passwords with special characters
If the password contains @, :, #, ?, or spaces, encode it before building the proxy URL. Otherwise the URL parser can split the credential into the wrong fields.
from urllib.parse import quote
user = quote(os.environ['PROXY_USER'], safe='')
password = quote(os.environ['PROXY_PASS'], safe='')
proxy = f'socks5h://{user}:{password}@proxynade.net:2555'
Bandwidth does not match response.content
len(response.content) is not the billed bandwidth. The proxy can count request headers, CONNECT traffic, redirects, compressed and uncompressed transfer differences, failed requests, and retries. Your app usually credits itself for the final useful payload. That is why it looks like the app lies.
Cap retries. Log status codes. Store the URL that caused each retry. Most wasted gigabytes come from one bad loop.
A safe Python session wrapper
Wrap proxy creation instead of rebuilding strings across the codebase. It gives you one place for encoding, DNS choice, timeouts, and environment isolation.
from urllib.parse import quote
import requests
def proxied_session(user, password, host='proxynade.net', port=2555):
safe_user = quote(user, safe='')
safe_password = quote(password, safe='')
proxy = f'socks5h://{safe_user}:{safe_password}@{host}:{port}'
session = requests.Session()
session.trust_env = False
session.proxies = {'http': proxy, 'https': proxy}
return session
session = proxied_session(PROXY_USER, PROXY_PASS)
response = session.get('https://example.com', timeout=(10, 30))
The tuple timeout matters. The first value caps connection setup. The second caps read time. Without timeouts, one bad route can hold a worker until the queue looks dead.
What to log from Python
Log the proxy label, requested URL, final URL, status code, exception class, elapsed time, retry number, and response size. Do not log raw credentials. If a provider bill looks wrong later, this log tells you whether the app loop or the proxy meter created the gap.
Python SOCKS5 FAQ
Should I use socks5 or socks5h? Use socks5h when the proxy should resolve target DNS. That is the safer default for scraping.
Why does Requests ignore my proxy? Environment variables can override behavior. Set session.trust_env = False during controlled tests.
Can I use the same proxy for HTTP and HTTPS? Yes. Put the same SOCKS URL under both http and https keys.
Why does the bill exceed downloaded bytes? Requests only shows what your code receives. The proxy also sees setup, retries, redirects, and failed traffic.