Короткие ответы
Как задать прокси для urllib.request?
Передайте словарь в ProxyHandler, создайте build_opener и используйте open именно этого объекта. Ключ https выбирает назначения HTTPS; URL в значении описывает шлюз. Здесь не устанавливается глобальный opener.
Куда передавать логин и пароль?
Этот пример отдельно кодирует исходный логин и пароль как компоненты URL прокси. Пароль читается через скрытый ввод. Не вставляйте его в исходник, аргументы оболочки или открытый отчёт.
407 всегда будет HTTPError?
Нет. Отклонённый CONNECT может привести к URLError до получения HTTP-ответа назначения. Общее сообщение ошибки не доказывает неверный пароль: отдельно проверяются адрес, TLS и содержимое ответа.
Таймаут десять секунд ограничивает весь скрипт?
Нет. Он относится к блокирующим операциям сокета. У задания дополнительно должны быть общий срок, ограничение работы и намеренная политика повторов. Ограничение прочитанного тела — ещё одна отдельная граница.
Проверьте, какой клиент использует приложение
urllib.request поставляется с Python и не требует установки стороннего HTTP-пакета. Если рабочий код использует Requests или HTTPX, настройте этот клиент по его правилам. Одинаковый язык Python не делает сетевую конфигурацию общей для библиотек.
Исходный пример проверялся на CPython 3.12.14 в локальных фикстурах HTTP CONNECT и HTTPS, без живого пула Portproof. Это граница сохранённого примера, а не заявление о проверке всех версий и операционных систем. Перед переносом проверьте свой интерпретатор и поддержку SSL.
Соберите параметры HTTP-подключения
- Откройте Connection builder · English, выберите HTTP, нужный пул, доступную страну и ротацию.
- Сохраните полное имя пользователя с параметрами подключения; одна основа аккаунта недостаточна.
- Подготовьте текущий пароль прокси. Не заменяйте его паролем Portproof или ключом API.
- Сохраните код ниже как proxy_check.py и запустите python3 proxy_check.py в интерактивном терминале.
Скрипт остановится, если терминал не умеет скрывать пароль. Не исправляйте это вставкой секрета в код. Скрытый ввод защищает отображение, но не заражённое устройство или память процесса. Не публикуйте полный URL прокси и необработанный объект исключения.
Один запрос через отдельный opener
import getpass
import http.client
import ipaddress
import json
import ssl
import warnings
from urllib.error import HTTPError, URLError
from urllib.parse import quote, urlsplit
from urllib.request import (
HTTPRedirectHandler, HTTPSHandler, ProxyHandler,
build_opener, proxy_bypass,
)
TARGET = "https://api.portproof.org/v1/echo-ip"
GATEWAY = "gw.portproof.org:7000"
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
def main():
try:
# Stop if a terminal cannot hide the password.
warnings.simplefilter("error", getpass.GetPassWarning)
username = input("Full proxy username: ").strip()
password = getpass.getpass("Proxy password: ")
if not username or not password:
raise ValueError("Empty credential")
if proxy_bypass(urlsplit(TARGET).netloc):
print("A direct-routing exception matches the target. Review NO_PROXY or system proxy exceptions.")
return 1
credential = quote(username, safe="") + ":" + quote(password, safe="")
proxy = "http://" + credential + "@" + GATEWAY
context = ssl.create_default_context()
context.set_alpn_protocols(["http/1.1"])
opener = build_opener(
ProxyHandler({"https": proxy}),
HTTPSHandler(context=context),
NoRedirect(),
)
with opener.open(TARGET, timeout=10) as response:
if response.status != 200:
raise ValueError("Unexpected response")
body = response.read(16_385)
if len(body) > 16_384:
raise ValueError("Response too large")
payload = json.loads(body)
if not isinstance(payload, dict) or not isinstance(payload.get("ip"), str):
raise ValueError("Missing IP")
print("HTTP 200; exit IP:", ipaddress.ip_address(payload["ip"]))
return 0
except HTTPError as error:
print("HTTP status:", error.code)
error.close()
except getpass.GetPassWarning:
print("Run from an interactive terminal that supports hidden password input.")
except (URLError, OSError, ValueError, http.client.HTTPException):
print("Check failed. Check proxy settings, credentials, TLS and the echo response.")
except (EOFError, KeyboardInterrupt):
print("Check cancelled.")
return 1
if __name__ == "__main__":
raise SystemExit(main())
Ожидается HTTP 200 и JSON с корректным IP. Вывод описывает то, что увидело назначение для этого запроса. Он не подтверждает географию, будущий адрес или разрешение другого сайта. При проверке используется существующий трафик; новый заказ или финансовая операция не выполняются.
Разделите схему назначения и транспорт шлюза
В ProxyHandler ключ https указывает на HTTPS-назначение, а http:// в значении — на HTTP-шлюз. После CONNECT выполняется TLS с назначением. Не меняйте схему шлюза только из-за HTTPS в адресе страницы. Документация Python описывает обработчики, openers и исключения окружения.
quote(value, safe="") применяется отдельно к исходным значениям. Символы @, двоеточие, косая черта и процент не должны превратить пароль в другую часть URL. Не кодируйте целый URL и не повторяйте кодирование уже преобразованного пароля. Для полного логина используйте результат конструктора, не собирайте его вручную.
Прокси-авторизация и вход на сайт назначения раздельны. Исходник не задаёт логин сайта. TLS-проверка назначения остаётся включённой, но начальная передача Basic-данных HTTP-шлюзу не зашифрована этим TLS. Используйте доверенный путь к шлюзу; принимайте только допустимую цепочку сертификата.
Учтите исключения и границы чтения
Явный словарь не выбирает адрес шлюза из переменных среды, однако исключения прямого маршрута всё ещё имеют значение. Пример проверяет proxy_bypass и останавливается при совпадении. Просмотрите NO_PROXY, no_proxy и системные исключения локально. Не удаляйте политику рабочей сети ради успешного результата.
Opener принадлежит проверке: install_opener не вызывается, чужие запросы не получают новую глобальную конфигурацию. Перенаправления остановлены. Ответ 301 или 302 здесь означает необходимость проверить назначение, а не включить неограниченный переход на другие узлы.
Читается максимум 16 КиБ плюс байт для обнаружения превышения. Это не предел всего сетевого расхода и не общий таймер. Длительный поток, очередь заданий и повторные попытки требуют дополнительных ограничений в приложении. Не расширяйте одноразовую проверку до рабочего сборщика без такого решения.
Определите, получен ли ответ назначения
| Наблюдение | Что проверить |
|---|---|
| HTTP 401 или 403 | Назначение ответило внутри туннеля: проверить его правила, не подставлять пароль шлюза. |
| Ошибка до HTTP-статуса | Сверить CONNECT, адрес, TLS и формат ответа через проверку curl. |
| 301, 302, 307 или 308 | Пример не следует перенаправлению; проверить ожидаемый URL. |
| Сообщение о прямом исключении | Проверить источник окружения и политику маршрута. |
| Нельзя скрыть пароль | Использовать подходящий терминал, не оставлять пароль в исходнике. |
Для авторизации есть инструкция 407, а при разных результатах клиентов — сравнение среды приложения. Меняйте один фактор и сохраняйте короткий результат без секретов.
Сохраните область действия примера
Использованный стандартный обработчик — HTTP-клиент прокси; SOCKS5 он не добавляет. Opener Python также не равен sticky-сессии шлюза. Выберите сессию в полном имени пользователя и сохраняйте одну конфигурацию для связанных шагов. Общие мобильный и резидентский пулы не гарантируют постоянный IP.
Перед большим заданием измерьте собственный разрешённый сценарий и ознакомьтесь с тарифами. Кабинет и покупка остаются на английском. Официальные справки проверены 31 октября 2026 года; тело сохранённого примера не изменено. Новая проверка живого шлюза, скорости или страны не проводилась.
Допустимое использование
Используйте прокси для разрешённых задач и соблюдайте правила принимающего сервиса. Настройка соединения не даёт права на доступ. Применяются правила допустимого использования · English.