ProxyError у requests: Unable to connect to proxy

Бібліотека requests не змогла пройти через проксі: або не з'єдналася з ним, або проксі відмовився відкривати тунель до сайту. Що саме сталося, видно з довгого тексту помилки.

Оновлено · Редакція Prokso

Коротко
  • ProxyError означає, що requests не пройшов через проксі: не під'єднався або не отримав тунель
  • Справжню причину видно в дужках після Caused by, а слово після 407 чи 503 називає її точно
  • Задайте рядок проксі зі схемою http:// для обох ключів словника і перевірте змінні середовища

Що означає помилка

Повідомлення виглядає так: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url: / (Caused by ProxyError('Unable to connect to proxy', ...)). Головне стоїть у дужках після Caused by. Бібліотека urllib3, на якій працює requests, загортає справжню причину в ProxyError, а requests видає її як requests.exceptions.ProxyError.

Слова Max retries exceeded не означають, що спроб було багато. За документацією requests за замовчуванням не повторює невдалі з'єднання, тож цей текст з'являється вже після першої спроби. У старій гілці urllib3 1.26 замість Unable to connect to proxy писалося Cannot connect to proxy. Сенс той самий.

Усередині зазвичай один із двох варіантів. NewConnectionError з Connection refused або ConnectTimeoutError означає, що до проксі не вдалося навіть під'єднатися. OSError('Tunnel connection failed: 407 NO_USER') означає, що з'єднання з проксі є, але на запит CONNECT він відповів не кодом 200. Після коду стоїть текст відповіді, і в Prokso він називає причину: NO_USER, TRAFFIC_EXHAUSTED, THREADS_EXHAUSTED, NO_RAY або NO_HOST_CONNECTION.

Причини

  • Хибний хост або порт. Connection refused або тайм-аут під'єднання: у рядку не gw.prokso.com або порт поза 823, 824 і 10000–20000.
  • Логін чи пароль не прийнято. Tunnel connection failed: 407 NO_USER означає помилку в логіні або паролі. Якщо ви входите за IP, поточної адреси немає у списку дозволених.
  • Вичерпано ліміт плану. 407 TRAFFIC_EXHAUSTED: закінчився трафік. 407 THREADS_EXHAUSTED: відкрито більше 1000 одночасних з'єднань на план.
  • Немає адреси під гео або сайт недоступний. 503 NO_RAY: під обрані країну, місто чи ASN зараз немає вільного IP. 502 NO_HOST_CONNECTION: проксі не зміг з'єднатися із сайтом.
  • Спецсимволи в паролі без кодування. Символи @, : або # у логіні чи паролі ламають розбір рядка, і до проксі доходять не ті дані.

Як виправити

  1. Скопіюйте рядок проксі з особистого кабінету заново й задайте його для обох ключів: proxies={'http': 'http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823', 'https': 'http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823'}. Схема самого проксі тут http://, навіть коли сайт працює на https://.
  2. Якщо в паролі є спецсимволи, закодуйте логін і пароль через urllib.parse.quote(ПАРОЛЬ, safe='') перед тим, як вставити їх у рядок.
  3. Прочитайте слово після коду в Tunnel connection failed. За NO_USER перевірте логін і список IP, за TRAFFIC_EXHAUSTED поповніть трафік, за THREADS_EXHAUSTED зменште кількість потоків, за NO_RAY розширте гео.
  4. Перевірте змінні середовища HTTP_PROXY, HTTPS_PROXY і ALL_PROXY. Requests їх читає, і документація попереджає, що вони можуть перекрити session.proxies. Надійніше передавати proxies= у кожен запит.
  5. Задайте timeout=(10, 30) і додайте повтор із паузою для 502 і 503: на порту 823 повтор піде вже через інший IP. Повний приклад є в інструкції Python requests, а загальний порядок пошуку причини описано на сторінці усунення несправностей.

Як перевірити, що все запрацювало

Виконайте requests.get('https://prokso.com/ip', proxies=proxies, timeout=30).json(). Якщо у відповіді IP і країна проксі, а не ваші, з'єднання працює. Той самий рядок можна перевірити без коду в перевірці проксі: якщо там усе гаразд, причину треба шукати в коді або змінних середовища.

Діагностика за 2 хвилини

Спершу вставте рядок у перевірку проксі. Якщо там проксі працює, причина в програмі чи її налаштуваннях. Якщо ні — перевірте рядок з терміналу:

curl -v -x "http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823" https://api.ipify.org
  • Рядок < HTTP/1.1 407 одразу після CONNECT — відповідає проксі. Назва після коду, наприклад NO_USER, підказує причину.
  • Проксі відповів на CONNECT кодом 200, а далі прийшов інший код — проксі працює, цю відповідь дав сайт.
  • Жодної відповіді, лише тайм-аут — з'єднання не дійшло до проксі: перевірте хост, порт і мережу.

Інструкції, де трапляється ця помилка

Питання й відповіді

Чому для http-сайту 407 приходить як відповідь, а не як виняток?

Для адрес http:// requests не відкриває тунель, а надсилає запит проксі напряму. Тому 407 повертається як звичайний response.status_code. Тунель CONNECT потрібен лише для https://, і там відмова стає винятком ProxyError. Що означає сам код, пояснено на сторінці <a href="/errors/407-proxy-authentication-required">407 Proxy Authentication Required</a>.

Що робити, якщо всередині ConnectTimeoutError?

Проксі не відповів за відведений час під'єднання. Перевірте хост і порт, мережу та фаєрвол, а потім сторінку <a href="/errors/proxy-timeout">тайм-аут проксі</a>.

Чому сайт бачить мою адресу, хоча проксі задано?

Найчастіше в словнику є лише ключ 'http', а сайт працює на https://. Ключ відповідає схемі сайту, тож запити до https:// ідуть напряму. Задайте обидва ключі.

Чи достатньо перехоплювати лише ProxyError?

ProxyError є підкласом requests.exceptions.ConnectionError. Помилки SOCKS-проксі requests видає як ConnectionError, тому, якщо працюєте з обома протоколами, перехоплюйте ConnectionError.

Резидентські $1.59, мобільні $2.50, серверні $0.65 за 1 ГБ

Реєстрація за хвилину, доступи одразу після оплати.

Створити акаунт