Как подключить прокси в Python: requests, Scrapy и Selenium
Подключение прокси в Python занимает одну строку, но в трёх местах легко ошибиться так, что всё будет «работать» и при этом течь мимо прокси. Разберём requests, Scrapy и Selenium, и что проверить после настройки.
requests: базовый случай
Прокси передаётся словарём с ключами по схемам. Один и тот же адрес указывается и для http, и для https — это адрес прокси, а не сайта, поэтому схема в значении описывает протокол подключения к самому прокси.
import requests
PROXY = "http://ЛОГИН:ПАРОЛЬ@ШЛЮЗ:ПОРТ"
proxies = {"http": PROXY, "https": PROXY}
r = requests.get("https://example.com", proxies=proxies, timeout=20)
print(r.status_code, r.text[:200])Логин, пароль, адрес шлюза и порт берутся в личном кабинете после оплаты тарифа. Таймаут ставьте всегда: без него зависший запрос остановит поток навсегда, а в многопоточном парсере это тихо съедает лимит подключений.
SOCKS5 и подводный камень с DNS
Если нужен SOCKS5, ставьте отдельную зависимость и обращайте внимание на букву h в схеме. Это самая частая незаметная ошибка в настройке.
# SOCKS5 требует дополнительной зависимости:
# pip install "requests[socks]"
PROXY = "socks5h://ЛОГИН:ПАРОЛЬ@ШЛЮЗ:ПОРТ"
proxies = {"http": PROXY, "https": PROXY}
# socks5h, а не socks5: с буквой h DNS-запрос уходит через прокси.
# Без неё имя домена резолвит ваша машина, и провайдер видит,
# какие сайты вы открываете, даже когда трафик идёт через прокси.Scrapy: middleware и согласование с тарифом
В Scrapy прокси задаётся через meta запроса, а сам механизм включается встроенным middleware. Второй важный момент — CONCURRENT_REQUESTS: это число должно быть не больше числа потоков в тарифе, иначе лишние запросы будут ждать освобождения слота.
# settings.py
DOWNLOADER_MIDDLEWARES = {
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 110,
}
CONCURRENT_REQUESTS = 50 # не больше числа потоков в тарифе
CONCURRENT_REQUESTS_PER_DOMAIN = 50
RETRY_TIMES = 3
# middlewares.py
class ProxyMiddleware:
def process_request(self, request, spider):
request.meta["proxy"] = "http://ЛОГИН:ПАРОЛЬ@ШЛЮЗ:ПОРТ"Если поставить CONCURRENT_REQUESTS заметно выше лимита, парсер не сломается — он просто начнёт работать медленнее ожидаемого, и причину этого потом сложно найти по логам.
Selenium: почему не работает пароль
Браузер — отдельный случай. Chrome игнорирует логин и пароль, переданные в --proxy-server, и вместо этого показывает системное окно авторизации, которое драйвер не заполнит.
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://ШЛЮЗ:ПОРТ")
driver = webdriver.Chrome(options=options)
# Chrome не принимает логин и пароль в --proxy-server: он их проигнорирует
# и покажет системное окно авторизации. Поэтому для браузера удобнее
# авторизация по IP — добавьте адрес машины в whitelist в кабинете.Обходных путей два: расширение, подставляющее учётные данные, либо авторизация по IP. Второй проще и надёжнее — добавьте адрес машины в whitelist, и браузер подключится без пароля. Оба способа авторизации у нас работают одновременно, так что скрипты могут продолжать ходить по логину.
Как проверить, что всё подключилось
После настройки сделайте два запроса подряд и посмотрите на возвращаемый адрес. Если включена ротация на каждый запрос, адреса будут разными — это и есть подтверждение, что трафик действительно идёт через пул.
import requests
PROXY = "http://ЛОГИН:ПАРОЛЬ@ШЛЮЗ:ПОРТ"
proxies = {"http": PROXY, "https": PROXY}
# Два запроса подряд должны вернуть разные адреса,
# если включена ротация на каждый запрос.
for _ in range(2):
print(requests.get("https://op-proxy.com/api/check",
proxies=proxies, timeout=20).text)- Адрес не меняется — вероятно, включена ротация по таймеру, а не на запрос.
- Виден ваш домашний адрес — прокси не применился, проверьте схему в словаре.
- Ошибка авторизации — проверьте, не истёк ли тариф и совпадает ли IP машины с whitelist.
Таймаут: почему одно число — плохая идея
Таймаут в requests принимает не только число, но и пару значений: сколько ждать установки соединения и сколько — ответа. Разница практическая: соединение либо устанавливается за доли секунды, либо не устанавливается вовсе, а ответ от нагруженной страницы может идти десятки секунд.
# Таймаут задавайте кортежем: (на соединение, на чтение).
# Одно число ставит одинаковый лимит на оба этапа, и это почти никогда не то,
# что нужно: соединение должно устанавливаться быстро, а ответ может быть долгим.
r = requests.get(url, proxies=proxies, timeout=(5, 30))
# Почему таймаут на соединение должен быть маленьким:
# requests и urllib3 НЕ реализуют Happy Eyeballs. Если у хоста есть и A, и AAAA,
# адреса пробуются последовательно, и фактический лимит на подключение
# удваивается — 5 секунд превращаются в 10 при недоступном IPv6.Отдельная тонкость, которая объясняет странно долгие зависания через IPv6-прокси. Библиотеки вроде curl и браузеры пробуют IPv4 и IPv6 почти одновременно, давая IPv6 небольшую форму. Requests так не делает — адреса перебираются по очереди, поэтому при недоступном IPv6 вы ждёте полный таймаут дважды.
Что проверить, когда «не работает»
Порядок важен: каждый шаг отсекает целый класс причин, и пропуск первого заставляет искать ошибку там, где её нет.
- Один и тот же адрес без прокси — если и так не отвечает, дело в сети или в самом сайте.
- Тот же прокси через curl с ключом -v — видно, пустил ли он вообще, до запроса к сайту.
- Заведомо открытый эндпоинт через прокси — отделяет отказ прокси от отказа целевого ресурса.
- Схема в словаре: для https-адреса значение описывает протокол до прокси, а не до сайта.
Пул для парсинга на Python
HTTP и SOCKS5, авторизация по логину и по IP одновременно. IPv6 от 650 ₽ за 50 потоков, выдача сразу после оплаты.
Смотреть тарифыПрокси под эту задачу
Проверить нашими инструментами
Читайте также
- Автоматизация прокси через API: whitelist, покупка и продление из скриптаPUT на whitelist заменяет список целиком, а не дополняет его — на этом теряют доступ. Разбор нашего API: ключ и лимиты, обновление адреса по cron, покупка и продление, коды ошибок.
- Прокси с логином и паролем в Selenium: почему сломались все старые рецептыЗа 2025 год Chrome убрал четыре разные вещи, и каждая ломает свою строчку десятилетнего туториала. Что именно перестало работать, чего в MV3 не потеряли и четыре пути, которые работают сейчас.
- Прокси в Key Collector: почему аккаунтным модулям нужна статика, а не ротацияПрограмма делится на модули, и правильный прокси у них разный. Аккаунт закрепляет за собой один адрес до перезапуска, Google.Ads не принимает IPv6 и SOCKS, а браузерный обработчик теряет SOCKS целиком.
