Каждая Python HTTP-библиотека принимает прокси как URL вида scheme://user:pass@host:port; различаются имя параметра, устанавливается ли он для клиента или для каждого запроса, а также обработка SOCKS5 и DNS. Приведенные ниже фрагменты — это точный код, который работает с текущими версиями requests, httpx и aiohttp — каждый был протестирован через прокси с аутентификацией перед публикацией этой статьи — а затем три вещи, которые вызывают большинство вопросов «мой прокси не работает в Python»: неправильные имена параметров, скопированные из старых руководств, отсутствующие дополнительные зависимости для SOCKS и TLS-отпечаток, который выдает скрипт независимо от IP.
URL прокси
http://user:pass@proxy.example.com:8080 # HTTP прокси, используется для целей http:// и https://
socks5://user:pass@proxy.example.com:1080 # SOCKS5, DNS резолвится локально
socks5h://user:pass@proxy.example.com:1080 # SOCKS5, DNS резолвится прокси (используйте это)
Два момента, которые часто сбивают с толку. Во-первых, HTTP-прокси также обрабатывает HTTPS-цели — клиент отправляет CONNECT и туннелирует TLS через него — поэтому вам почти никогда не нужна схема https:// для прокси; это означало бы TLS к самому прокси, что предлагают немногие провайдеры. Во-вторых, если ваше имя пользователя содержит параметры ротации (user-country-de-session-abc123) или ваш пароль содержит @, : или /, закодируйте их в процентах (urllib.parse.quote(pw, safe='')), иначе URL будет разобран неправильно.
requests
import requests
PROXY = "http://user:pass@proxy.example.com:8080"
proxies = {"http": PROXY, "https": PROXY}
# для каждого запроса
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.json())
# для сессии (переиспользует соединения; обычный способ)
s = requests.Session()
s.proxies.update(proxies)
r = s.get("https://api.ipify.org?format=json", timeout=20)
Словарь ключуется по схеме цели: запросы к URL http:// используют запись "http", запросы к https:// — "https". Установите оба значения на один и тот же прокси, если нет причин поступать иначе. Всегда передавайте timeout; зависший прокси иначе зависнет ваш скрипт навсегда.
SOCKS5 требует дополнительную зависимость: pip install "requests[socks]". Затем proxies = {"http": "socks5h://…", "https": "socks5h://…"}. Без этой зависимости вы получите InvalidSchema: Missing dependencies for SOCKS support.
Переменные окружения: requests по умолчанию учитывает HTTP_PROXY / HTTPS_PROXY / NO_PROXY (trust_env=True). Если прокси таинственно используется, когда вы его не задавали, или не используется, когда задавали, проверьте окружение.
httpx
import httpx
PROXY = "http://user:pass@proxy.example.com:8080"
# синхронно
with httpx.Client(proxy=PROXY, timeout=20) as client:
r = client.get("https://api.ipify.org?format=json")
print(r.json())
# асинхронно
import asyncio
async def main():
async with httpx.AsyncClient(proxy=PROXY, timeout=20) as client:
r = await client.get("https://api.ipify.org?format=json")
print(r.json())
asyncio.run(main())
Параметр называется proxy= (в единственном числе). Старые руководства показывают proxies={"http://": …, "https://": …}; это ключевое слово было устаревшим в httpx 0.26 и удалено в 0.28, и его передача теперь вызывает TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. Если вам нужны разные прокси для разных целей, используйте mounts:
mounts = {
"https://api.example.com": httpx.HTTPTransport(proxy="http://user:pass@dc-proxy:8080"),
"all://": httpx.HTTPTransport(proxy="http://user:pass@resi-proxy:8080"),
}
client = httpx.Client(mounts=mounts)
SOCKS5: pip install "httpx[socks]", затем proxy="socks5://…". httpx по умолчанию резолвит hostname через SOCKS-прокси. HTTP/2: pip install "httpx[http2]" и httpx.Client(http2=True, …) — это важно, потому что проксированный браузер в любом случае работает по HTTP/2 (см. HTTP/2 и HTTP/3 через прокси).
aiohttp
import aiohttp, asyncio
PROXY = "http://user:pass@proxy.example.com:8080"
async def main():
async with aiohttp.ClientSession() as session:
async with session.get("https://api.ipify.org?format=json",
proxy=PROXY,
timeout=aiohttp.ClientTimeout(total=20)) as r:
print(await r.json())
asyncio.run(main())
Прокси передается в каждом запросе (или устанавливается один раз через кастомный коннектор). Учетные данные указываются в URL; отдельная форма proxy_auth=aiohttp.BasicAuth(...) все еще работает в 3.x, но устарела начиная с 3.14 и планируется к удалению в 4.0, поэтому предпочтительнее форма URL. aiohttp не читает переменные окружения HTTP_PROXY, если только вы не создаете сессию с trust_env=True. Нативный aiohttp поддерживает только HTTP-прокси; для SOCKS используйте пакет aiohttp-socks и его ProxyConnector.
Ротация прокси: паттерн session-ID
С помощью шлюза с обратным подключением (см. как работают шлюзы ротации) вам редко приходится ротировать в Python вообще — вы ротируете, изменяя имя пользователя. Новый session ID означает новый выходной IP; повторное использование сохраняет его:
import secrets, requests
def proxy_for(session_id: str, country: str = "de") -> dict:
user = f"customer-country-{country}-session-{session_id}" # формат зависит от провайдера
url = f"http://{user}:PASSWORD@gate.provider.com:7777"
return {"http": url, "https": url}
# sticky: один и тот же IP для многошагового процесса
sid = secrets.token_hex(4)
s = requests.Session(); s.proxies.update(proxy_for(sid))
s.get("https://shop.example/login"); s.post("https://shop.example/cart", data=...)
# rotating: новый IP для каждого элемента
for url in urls:
requests.get(url, proxies=proxy_for(secrets.token_hex(4)), timeout=20)
Ротируйте также при ошибках: перехватывайте 403/429 и маркер CAPTCHA, и повторяйте с новым session ID и новой cookie-корзиной — тот же IP с теми же cookie означает того же посетителя.
Ошибка, которую не исправит ни один прокси: TLS-отпечаток
Все три библиотеки устанавливают TLS-соединения через модуль ssl Python (OpenSSL). Антибот-системы снимают отпечаток этого рукопожатия и понимают, что это не браузер, независимо от того, как вы установите User-Agent. За идеальным резидентным IP скрипт все равно идентифицируется как скрипт — механизм описан в статье TLS fingerprinting explained. Для защищенных целей переключитесь на клиент с имитацией; curl_cffi сохраняет API, похожий на requests:
# pip install curl_cffi
from curl_cffi import requests as cffi_requests
r = cffi_requests.get("https://protected.example/",
impersonate="chrome", # воспроизводит TLS + HTTP/2 отпечаток Chrome
proxies={"https": "http://user:pass@proxy.example.com:8080"},
timeout=20)
Затем сохраняйте согласованность остальной части истории — User-Agent Chrome, соответствующие client hints sec-ch-ua, Accept-Language, правдоподобный для страны прокси. Для сайтов, которые дополнительно требуют JavaScript-задач, ни один HTTP-клиент не подойдет; используйте настоящий браузер, как в статье Прокси в Playwright, Puppeteer и Selenium.
Ошибки и что они означают
| Вы видите | Это означает | Исправление |
|---|---|---|
ProxyError … 407 Proxy Authentication Required | Неверные учетные данные или ваш IP не в белом списке | Проверьте user/pass (длинные строки ротации!), закодируйте спецсимволы, проверьте белый список |
InvalidSchema: Missing dependencies for SOCKS support | requests без дополнительной зависимости для socks | pip install "requests[socks]" |
TypeError: … unexpected keyword argument 'proxies' | httpx ≥ 0.28 с удаленным параметром | Используйте proxy= или mounts= |
ProxyError … Cannot connect to proxy / ConnectTimeout | Неверный host/port, прокси не работает или файрвол | Проверьте с помощью curl -x; попробуйте другой протокол |
| Реальный IP возвращается эхо-сервисом IP | Прокси не применен (неверный ключ словаря, переопределение env var, отсутствует параметр per-request в aiohttp) | Выведите session.proxies; проверьте trust_env; передайте proxy= в запросе |
SSLError только через прокси | Прокси перехватывает TLS (MITM) или неверная схема | Используйте схему http:// для прокси; уточните у провайдера, завершают ли они TLS |
| 403/CAPTCHA на защищенных сайтах, IP выглядит нормально | TLS/HTTP отпечаток выдает Python | curl_cffi с impersonate или настоящий браузер |
| Работает какое-то время, затем 429 | Достигнут лимит запросов на IP | Ротируйте session ID; замедлитесь; см. руководство по ротации |
Минимальный корректный шаблон
import requests, secrets
from urllib.parse import quote
GATE, PORT = "gate.provider.com", 7777
USER_BASE, PASS = "customer-country-de", quote("p@ss:word", safe="")
def make_session() -> requests.Session:
sid = secrets.token_hex(4)
url = f"http://{USER_BASE}-session-{sid}:{PASS}@{GATE}:{PORT}"
s = requests.Session()
s.proxies.update({"http": url, "https": url})
s.headers.update({"User-Agent": "python-requests"}) # честный UA для нетребовательных целей
return s
s = make_session()
r = s.get("https://api.ipify.org?format=json", timeout=20)
r.raise_for_status()
print(r.json())
Убедитесь, что IP меняется, затем развивайте. Для полной предварительной проверки (утечки, заголовки, блок-листы) см. Как тестировать прокси; для выбора между датацентровыми и резидентными прокси для конкретной цели — сравнение типов прокси.
Часто задаваемые вопросы
Как использовать прокси с Python requests?
Передайте proxies={"http": url, "https": url} в запрос или установите его на Session, где url — это http://user:pass@host:port. Добавьте timeout=. Для SOCKS5 установите requests[socks] и используйте socks5h://.
Почему httpx говорит ‘unexpected keyword argument proxies’?
Потому что proxies= был удален в httpx 0.28. Используйте proxy="http://…" для одного прокси или mounts= для прокси по целям.
Как установить прокси в aiohttp?
Передайте proxy="http://user:pass@host:port" в каждый запрос (session.get(url, proxy=…)). Параметр proxy_auth= устарел; поместите учетные данные в URL. Для SOCKS используйте aiohttp-socks.
Как ротировать прокси в Python?
С провайдером с обратным подключением меняйте session ID в имени пользователя прокси для каждого запроса или процесса — список IP не нужен. Ротируйте при 403/429 и сочетайте каждый новый IP с новой cookie-корзиной.
Почему мой скрипт блокируется, когда мой браузер на том же прокси — нет?
TLS и HTTP/2 отпечатки: модуль ssl Python не выглядит как браузер. Используйте curl_cffi с impersonate= или автоматизируйте настоящий браузер.
Стоит ли использовать socks5 или socks5h?
socks5h. Буква h заставляет прокси резолвить hostname, предотвращая утечки DNS и позволяя достигать хостов, которые может резолвить только прокси.