Прокси в Python: requests, httpx и Playwright
Опубликовано 6 минут чтения
Коротко
В requests прокси передают словарём proxies с ключами http и https, в httpx — аргументом proxy, в Playwright — параметром proxy с полями server, username и password. Для SOCKS5 в requests нужен пакет PySocks и схема socks5h. Chromium через Playwright не принимает SOCKS5 с логином и паролем, поэтому в браузере используйте HTTP: у Proxeta это порт 8080.
Ниже — как подключить прокси с логином и паролем в requests, httpx и Playwright для Python, как управлять сменой IP и как читать ошибки. Данные в примерах условные: подставьте свои из личного кабинета. Выходной IP примеры узнают у сервиса api64.ipify.org, который возвращает адрес, с которого к нему пришёл запрос.
Строка прокси в формате URL
Личный кабинет выдаёт строку host:port:login:password, а Python-библиотеки ждут URL: http://login:password@host:8080 для HTTP или socks5h://login:password@host:1080 для SOCKS5. Функция ниже переводит одно в другое и кодирует логин и пароль, если в них есть @, : или /:
from urllib.parse import quote
def proxy_url(line, scheme="http"):
host, port, login, password = line.strip().split(":", 3)
return f"{scheme}://{quote(login, safe='')}:{quote(password, safe='')}@{host}:{port}"
print(proxy_url("proxy.example.invalid:8080:login-country-us:password"))
print(proxy_url("proxy.example.invalid:1080:login-country-us:password", "socks5h"))
split(":", 3) делит строку не больше чем на четыре части, поэтому двоеточие в пароле не мешает. Логины в примерах сокращены: в строке из личного кабинета есть ещё параметр фильтра, например -filter-medium, поэтому копируйте её целиком. Из чего состоит логин, разобрано в статье формат строки прокси.
requests: HTTP и SOCKS5
Нужен пакет: pip install requests.
import requests
PROXY = "http://login-country-us:password@proxy.example.invalid:8080"
PROXIES = {"http": PROXY, "https": PROXY}
r = requests.get("https://api64.ipify.org?format=json", proxies=PROXIES, timeout=(10, 30))
r.raise_for_status()
print(r.json()["ip"])
Что важно в этом коде:
- Оба ключа. Ключ словаря — схема сайта, значение — адрес прокси. Если указать только
"http", запросы к https://-сайтам пойдут напрямую, мимо прокси. - Схема значения — http:// и для ключа
"https": requests открывает к прокси обычное соединение и туннель CONNECT.https://в адресе прокси означало бы TLS-соединение до самого прокси, а это другой тип прокси. - Таймаут.
timeout=(10, 30)— 10 секунд на подключение и 30 на ожидание ответа. Без таймаута requests может ждать ответа бесконечно.
Для SOCKS5 поставьте пакет PySocks командой pip install "requests[socks]" и замените адрес:
PROXY = "socks5h://login-country-us:password@proxy.example.invalid:1080"
С socks5h:// имя сайта разрешает прокси, с socks5:// — ваше устройство, и адрес сайта может подбираться для вашей локации, а не для локации выхода; подробнее — в статье HTTP или SOCKS5. Без PySocks requests остановится с ошибкой Missing dependencies for SOCKS support.
Сессии и смена IP
При ротации (логин без -sid-) новый IP получает каждое новое соединение. requests.Session держит соединение открытым и отправляет через него следующие запросы, а requests.get без сессии каждый раз открывает новое. Сравните:
import requests
PROXY = "http://login-country-us:password@proxy.example.invalid:8080"
PROXIES = {"http": PROXY, "https": PROXY}
URL = "https://api64.ipify.org?format=json"
with requests.Session() as session:
print([session.get(URL, proxies=PROXIES, timeout=(10, 30)).json()["ip"] for _ in range(3)])
print([requests.get(URL, proxies=PROXIES, timeout=(10, 30)).json()["ip"] for _ in range(3)])
Первая строка вывода — три одинаковых адреса: все запросы прошли через одно соединение. Во второй адреса меняются: у каждого запроса своё соединение. Если сервер закроет соединение сессии, она откроет новое, и при ротации адрес тоже сменится.
Если адрес должен сохраняться между запросами — например, после входа в аккаунт или на шагах формы, — возьмите строку липкой сессии с -sid-: с ней все шесть запросов из примера выходят с одного адреса, пока жива сессия. Когда какой режим выбирать, разобрано в статье sticky-сессия или ротация.
httpx
Нужен пакет: pip install httpx. httpx принимает прокси аргументом proxy; старый аргумент proxies в версии 0.28 удалён, и с ним клиент не создаётся.
import httpx
PROXY = "http://login-country-us:password@proxy.example.invalid:8080"
with httpx.Client(proxy=PROXY, timeout=30) as client:
r = client.get("https://api64.ipify.org?format=json")
r.raise_for_status()
print(r.json()["ip"])
Тот же аргумент принимает асинхронный клиент:
import asyncio
import httpx
PROXY = "http://login-country-us:password@proxy.example.invalid:8080"
async def main():
async with httpx.AsyncClient(proxy=PROXY, timeout=30) as client:
r = await client.get("https://api64.ipify.org?format=json")
r.raise_for_status()
print(r.json()["ip"])
asyncio.run(main())
Клиент httpx тоже держит соединения открытыми, поэтому при ротации запросы одного клиента могут выходить с одного адреса. Для SOCKS5 httpx нужен дополнительный пакет httpx[socks], а без него клиент остановится с ошибкой ImportError; в этой статье SOCKS5 показан на requests.
Playwright: прокси с логином и паролем
Нужны пакет и браузер: pip install playwright и playwright install chromium.
from playwright.sync_api import sync_playwright
PROXY = {
"server": "http://proxy.example.invalid:8080",
"username": "login-country-us-sid-k7m2q9x4ab",
"password": "password",
}
with sync_playwright() as p:
browser = p.chromium.launch(proxy=PROXY)
try:
page = browser.new_page()
page.goto("https://api64.ipify.org?format=json", timeout=60000)
print(page.inner_text("body"))
finally:
browser.close()
- Поля. Логин и пароль передаются отдельными полями
usernameиpassword, а вserver— только схема, хост и порт. - Липкая сессия. Браузер открывает несколько соединений даже на одну страницу, и при ротации они могли бы выйти с разных адресов. Поэтому в примере строка с
-sid-.
Если разным задачам нужны разные адреса, задайте прокси на уровне контекста: у каждого контекста свои cookies и свой прокси. В примере ниже один контекст выходит из США, другой — из Германии:
from playwright.sync_api import sync_playwright
LOGINS = ["login-country-us-sid-k7m2q9x4ab", "login-country-de-sid-p3w8n1c5zd"]
with sync_playwright() as p:
browser = p.chromium.launch()
try:
for login in LOGINS:
context = browser.new_context(proxy={
"server": "http://proxy.example.invalid:8080",
"username": login,
"password": "password",
})
page = context.new_page()
page.goto("https://api64.ipify.org?format=json", timeout=60000)
print(login, page.inner_text("body"))
context.close()
finally:
browser.close()
Почему не SOCKS5
Chromium через Playwright не работает с SOCKS5 по логину и паролю. Запуск с "server": "socks5://proxy.example.invalid:1080" и полями username и password останавливается ошибкой Browser does not support socks5 proxy authentication. Если вместо этого записать логин и пароль в сам адрес socks5://, запуск проходит, но браузер их не передаёт: он предлагает прокси только подключение без входа, прокси с обязательным логином отказывает, и page.goto завершается ошибкой net::ERR_SOCKS_CONNECTION_FAILED. Поэтому в Playwright используйте HTTP — порт 8080. Firefox и WebKit мы не проверяли.
Ошибки и что они значат
Номер ошибки в Connection refused зависит от системы: на macOS это [Errno 61], на Linux — [Errno 111].
| Библиотека | Сообщение | Что это значит |
|---|---|---|
| requests | ProxyError: ... Tunnel connection failed: 407 Proxy Authentication Required | HTTP-прокси не принял логин или пароль |
| requests | ConnectionError: ... SOCKS5 authentication failed | SOCKS5-прокси не принял логин или пароль |
| requests | ProxyError: ... Failed to establish a new connection: [Errno 61] Connection refused | Соединение с прокси не установилось: неверный порт или исходящие соединения закрыты в вашей сети |
| requests | ProxyError: ... Failed to resolve 'proxy.example.invalid' | Адрес прокси не найден. Так завершается и пример без замены условного хоста |
| requests | InvalidSchema: Missing dependencies for SOCKS support. | Не установлен PySocks: pip install "requests[socks]" |
| httpx | ProxyError: 407 Proxy Authentication Required | Прокси не принял логин или пароль |
| httpx | ConnectError: [Errno 61] Connection refused | Соединение с прокси не установилось |
| Playwright | net::ERR_PROXY_CONNECTION_FAILED | Соединение с прокси не установилось |
| Playwright | net::ERR_SOCKS_CONNECTION_FAILED | Соединение через SOCKS5-прокси не установилось. Так заканчивается и попытка записать логин и пароль в адрес socks5://: Chromium их не передаёт |
| Playwright | Timeout 60000ms exceeded | Страница не загрузилась за отведённое время. В нашей проверке так выглядел и неверный пароль: Chromium не показал код 407 |
Если Playwright упирается в таймаут, проверьте ту же строку в requests или curl: там неверный логин или пароль видны по коду 407. Разбор ошибок curl — в статье curl через прокси.
Прокси не меняет правил сайта. Соблюдайте его условия и robots.txt, ограничивайте частоту запросов и не отвечайте на отказ сменой IP: подробнее — в руководстве по прокси для парсинга.
Как запускались примеры
Примеры запускались 5 ноября 2026 года на macOS в Python 3.11 с requests 2.33.1, PySocks 1.7.1, httpx 0.28.1 и Playwright 1.58.0 для Python — через локальные тестовые HTTP- и SOCKS5-прокси с логином и паролем и локальный сайт, а не через шлюз Proxeta. Обе проверки SOCKS5 в Playwright мы повторили в Playwright 1.62.1 для Node.js с Chromium 151. Для теста браузеру разрешили сертификат локального сайта. Так проверяются синтаксис и поведение библиотек, но не выходные IP и работа настоящей сети.
Частые вопросы
Как подключить прокси с логином и паролем в requests?
Передайте словарь proxies, где оба ключа, http и https, указывают на адрес вида http://логин:пароль@хост:8080. Если указать только http, запросы к https://-сайтам пойдут мимо прокси. Для SOCKS5 установите requests[socks] и используйте адрес socks5h://логин:пароль@хост:1080.
Почему Playwright не принимает SOCKS5 с паролем?
Chromium через Playwright не поддерживает вход в SOCKS5-прокси по логину и паролю: запуск останавливается ошибкой «Browser does not support socks5 proxy authentication». Мы проверили это 5 ноября 2026 года в Playwright 1.62.1 для Node.js с Chromium 151 и в Playwright 1.58.0 для Python. Используйте HTTP-прокси, у Proxeta это порт 8080.
Как получать новый IP на каждый запрос в Python?
Возьмите строку с ротацией, без параметра -sid- в логине, и открывайте новое соединение на каждый запрос: например, вызывайте requests.get без общей сессии. requests.Session держит соединение открытым, и через одно соединение запросы выходят с одного адреса.
Как задать разные прокси для разных контекстов Playwright?
Передайте параметр proxy в browser.new_context, а не в chromium.launch: у каждого контекста будут свои cookies и свой прокси. Для каждого контекста берите отдельную строку липкой сессии, чтобы все его соединения выходили с одного адреса.