# Прокси в aiohttp 3.14: авторизация, trust_env, ошибки

Source: https://ipvolt.com/ru/guides/aiohttp-proxy-setup
Markdown: https://ipvolt.com/ru/guides/aiohttp-proxy-setup.md
Language: ru

[ipvolt — главная](https://ipvolt.com/ru.md) / [Руководства](https://ipvolt.com/ru/guides.md) / Прокси в aiohttp 3.14: авторизация, trust_env, ошибки

Интеграция
Опубликовано: 2026-10-06
7 мин чтения
Автор: ipvolt

Настройка прокси в aiohttp 3.14: чем заменить устаревшие BasicAuth и proxy_auth, как включить trust_env и что означают ошибки 407 и Bad status line. Проверено на 3.14.4.

В aiohttp 3.14.0 (1 июня 2026 года) класс `BasicAuth` и параметр `proxy_auth` объявлены устаревшими ([список изменений](https://docs.aiohttp.org/en/stable/changes.html), [#12499](https://github.com/aio-libs/aiohttp/pull/12499)). Замена — заголовок `Proxy-Authorization`, собранный функцией `aiohttp.encode_basic_auth()`:

```python
import asyncio

import aiohttp

PROXY = "http://proxy.example.com:8080"
PROXY_HEADERS = {"Proxy-Authorization": aiohttp.encode_basic_auth("user", "pass")}


async def main() -> None:
    async with aiohttp.ClientSession(proxy=PROXY) as session:
        async with session.get("https://example.com/", proxy_headers=PROXY_HEADERS) as response:
            print(response.status)


asyncio.run(main())
```

В нашей лаборатории так авторизовался каждый запрос к `https://`, и `DeprecationWarning` не появлялся. Обычные запросы к `http://` не авторизовались: aiohttp 3.14.4 отправлял `proxy_headers` только с запросом `CONNECT`, который открывает HTTPS-туннель, поэтому для URL с `http://` прокси не получал учётных данных и отвечал 407.

| Как переданы учётные данные | URL с `https://` | URL с `http://` | Предупреждения об устаревании |
| --- | --- | --- | --- |
| `proxy_headers={"Proxy-Authorization": aiohttp.encode_basic_auth(...)}` | 200 | 407 | нет |
| `proxy="http://user:pass@host:port"` | 200 | 200 | нет |
| `proxy_auth=aiohttp.BasicAuth(...)` | 200 | 200 | два на каждый вызов |

Эти результаты записаны 6 октября 2026 года с aiohttp 3.14.4 и aiohttp-socks 0.12.0 на Python 3.14.4, с запуском через `python -W always` и локальным прокси, который требует Basic-авторизацию. aiohttp 3.14.0 и 3.14.3 дали те же результаты.

## Переход с proxy_auth=aiohttp.BasicAuth

Старый вызов в 3.14.4 по-прежнему работает для обеих схем URL:

```python
async with session.get(url, proxy=PROXY, proxy_auth=aiohttp.BasicAuth("user", "pass")) as response:
    print(response.status)
```

Каждый вызов печатал два предупреждения:

```text
DeprecationWarning: BasicAuth is deprecated and will be removed in aiohttp 4.0; use aiohttp.encode_basic_auth() with headers={'Authorization': ...} instead
DeprecationWarning: The 'proxy_auth' parameter is deprecated and will be removed in v4; pass proxy_headers={'Proxy-Authorization': aiohttp.encode_basic_auth(login, password)} instead
```

Замена:

```python
proxy_headers = {"Proxy-Authorization": aiohttp.encode_basic_auth("user", "pass")}
async with session.get(url, proxy=PROXY, proxy_headers=proxy_headers) as response:
    print(response.status)
```

Перед выкладкой проверьте четыре вещи:

- **Запросы к обычным `http://` теряют учётные данные.** В [документации](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support) `proxy_headers` показан с URL на `http://`. В лаборатории такой запрос дошёл до прокси без `Proxy-Authorization` и без дополнительного заголовка, который мы добавили в `proxy_headers`, и вернулся с кодом 407. В [issue #4422](https://github.com/aio-libs/aiohttp/issues/4422) о том же сообщали для aiohttp 3.6.2. Если вы запрашиваете URL с `http://`, укажите учётные данные в URL прокси: `proxy="http://user:pass@host:port"` вернул 200 для обеих схем без предупреждений.
- **У `ClientSession` нет аргумента `proxy_headers`.** В документации показан вызов `ClientSession(proxy=..., proxy_headers=...)`. В 3.14.4 он поднял `TypeError: ClientSession.__init__() got an unexpected keyword argument 'proxy_headers'`. Задайте `proxy=` у сессии, а `proxy_headers=` передавайте с каждым запросом, как в первом примере.
- **Не переносите заголовок в `headers=`.** Для URL с `https://` заголовки запроса идут внутри туннеля. Когда `Proxy-Authorization` был в `headers=`, целевой сервер лаборатории получил учётные данные прокси.
- **Кодировка по умолчанию изменилась.** `encode_basic_auth()` использует UTF-8, а `BasicAuth` использовал latin1. Для пароля `päss` значения заголовка получились разными, поэтому передайте `encoding="latin1"`, если ваш прокси ждёт прежние байты.

`encode_basic_auth()` появилась в 3.14 ([справочник](https://docs.aiohttp.org/en/stable/client_reference.html#aiohttp.encode_basic_auth)). На aiohttp 3.13.5 тот же код поднял `AttributeError: module aiohttp has no attribute encode_basic_auth`.

## Переменным окружения нужен trust_env=True

`ClientSession()` по умолчанию игнорирует переменные прокси. При заданной `HTTP_PROXY` запрос ушёл прямо к цели, а прокси ничего не записал в журнал. Эта сессия пошла через прокси:

```python
async with aiohttp.ClientSession(trust_env=True) as session:
    async with session.get("http://example.com/") as response:
        print(response.status)
```

В [документации](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support) сказано, что aiohttp читает переменные через `urllib.request.getproxies()`, применяет их к схемам HTTP, HTTPS, WS и WSS, пропускает мимо прокси хосты из `no_proxy` и может брать учётные данные прокси из `~/.netrc`. В лаборатории с `trust_env=True`:

- `HTTP_PROXY` и `http_proxy` в нижнем регистре применялись к URL с `http://`, а `HTTPS_PROXY` — к URL с `https://`. Когда была задана только `HTTP_PROXY`, запрос к `https://` шёл напрямую.
- `ALL_PROXY` игнорировалась.
- Учётные данные из URL в переменной авторизовали обе схемы, и предупреждений не было.
- `NO_PROXY=127.0.0.1` отправила запрос напрямую. На явный аргумент `proxy=` она не повлияла, и он же имел приоритет над переменной.
- Переменная с URL прокси на `https://` была пропущена. aiohttp записал `HTTPS proxies https://127.0.0.1:8888 are not supported, ignoring` и подключился напрямую.

[Переменные окружения прокси](/ru/guides/proxy-environment-variables) сравнивает эти правила в других клиентах.

## ClientHttpProxyError: 407 для URL с https://

Когда прокси отклоняет запрос `CONNECT`, aiohttp поднимает исключение раньше, чем что-либо дойдёт до целевого сервера. С неверным паролем в URL прокси:

```text
aiohttp.client_exceptions.ClientHttpProxyError: 407, message='Proxy Authentication Required', url='http://user:wrong@127.0.0.1:8888'
```

Пароль входит в сообщение, поэтому попадает туда же, куда и исключение: в журналы, трассировки, системы сбора ошибок. Когда учётные данные были в `proxy_headers` или брались из `HTTPS_PROXY`, тот же сбой печатал `url='http://127.0.0.1:8888'`.

Для трафика на `https://` держите учётные данные вне URL прокси. Там, где они нужны в URL, записывайте в журнал `exc.status` и `exc.message` (в лаборатории это `407` и `Proxy Authentication Required`), а не текст исключения. [Как исправить ошибку прокси 407](/ru/guides/fix-proxy-error-407) даёт порядок проверок на случай, когда учётные данные выглядят верными.

## Статус 407 без исключения для URL с http://

Для URL с `http://` ответ 407 от прокси — обычный ответ. Исключения нет, `response.status` равен 407, а заголовок `Proxy-Authenticate` содержит запрос авторизации. Код, который ловит только исключения, считает это успехом.

Проверяйте `response.status` или создавайте сессию с `raise_for_status=True`. Это подняло:

```text
aiohttp.client_exceptions.ClientResponseError: 407, message='Proxy Authentication Required', url='http://127.0.0.1:8080/'
```

`raise_for_status=True` у запроса и `response.raise_for_status()` подняли ту же ошибку. Класс здесь `ClientResponseError`, а URL — целевой, не прокси. `ClientHttpProxyError` — его подкласс, поэтому `except aiohttp.ClientResponseError` с проверкой `exc.status == 407` покрывает обе схемы.

## Bad status line: b'\x05\x00' при URL прокси с socks5://

aiohttp не отклоняет `proxy="socks5://..."`. Он отправляет на порт SOCKS HTTP-запрос и падает на ответе:

```text
aiohttp.client_exceptions.ClientResponseError: 400, message="Bad status line:\n  Expected HTTP/, RTSP/ or ICE/:\n\n  b'\\x05\\x00'\n    ^", url='http://127.0.0.1:8080/'
```

`\x05\x00` — начало ответа SOCKS5-сервера, прочитанное как строка статуса HTTP. С `socks5h://` сбой был таким же. Решение — SOCKS-коннектор, он показан ниже.

## ClientConnectorSSLError при URL прокси с https://

URL прокси с `https://` велит aiohttp открыть TLS до самого прокси. С лабораторным прокси, который говорит по обычному HTTP, запрос упал во время рукопожатия:

```text
aiohttp.client_exceptions.ClientConnectorSSLError: Cannot connect to host 127.0.0.1:8888 ssl:default [[SSL: RECORD_LAYER_FAILURE] record layer failure (_ssl.c:1081)]
```

Прокси увидел TLS ClientHello и ответил открытым текстом кодом 400. Схема в URL прокси описывает соединение с прокси, а не с целевым сервером: URL прокси с `http://` проводит запросы к `https://` через `CONNECT`. Текст ошибки приходит из OpenSSL 3.5.5 и в других версиях может выглядеть иначе.

## DeprecationWarning: BasicAuth is deprecated

Достаточно создать `aiohttp.BasicAuth(...)`, чтобы появилось первое предупреждение, ещё до запроса. Параметр `auth=` для учётных данных сайта тоже устарел. Его предупреждение называет заменой `headers={'Authorization': aiohttp.encode_basic_auth(login, password)}`.

Вы можете не увидеть ни одного из них. По умолчанию Python показывает `DeprecationWarning`, только когда [вызвавший его код находится в `__main__`](https://docs.python.org/3/library/warnings.html#default-warning-filter). В лаборатории устаревший вызов печатал предупреждения, когда был в запускаемом скрипте, и ничего не печатал, когда был в импортированном модуле. `python -W always` печатал их в обоих местах. `python -W error` превратил первое в исключение, и так в тестовом прогоне находится каждое место вызова.

## SOCKS-прокси: используйте aiohttp-socks

```sh
python -m pip install aiohttp-socks
```

```python
import aiohttp
from aiohttp_socks import ProxyConnector

connector = ProxyConnector.from_url("socks5://127.0.0.1:1080")
async with aiohttp.ClientSession(connector=connector) as session:
    async with session.get("https://example.com/") as response:
        print(response.status)
```

С [aiohttp-socks](https://pypi.org/project/aiohttp-socks/) 0.12.0 это вернуло 200 для URL с `http://` и `https://`, а SOCKS-сервер записал каждое соединение. Две детали:

- `socks5://` уже отправляет имя хоста на прокси. Для `http://localhost:8080/` сервер записал доменное имя. С `rdns=False` он записал `127.0.0.1`.
- `ProxyConnector.from_url("socks5h://...")` поднял `ValueError: Invalid scheme component: socks5h`. [SOCKS5 и SOCKS5h](/ru/blog/socks5-vs-socks5h) показывает, что каждый клиент делает с этими двумя схемами.

Requests и HTTPX нужны собственные пакеты для SOCKS, о них рассказано в руководстве [Missing dependencies for SOCKS support](/ru/guides/fix-missing-dependencies-for-socks-support).

## Повторные попытки после ошибок прокси

Ошибка 407, ошибка строки статуса от SOCKS и ошибка TLS выше — ошибки конфигурации. Тот же запрос снова упадёт так же, поэтому исправляйте настройку, а не повторяйте запрос. При таймаутах и оборванных соединениях повторяйте только те запросы, которые безопасно повторять. `POST` мог дойти до целевого сервера до того, как оборвалось соединение с прокси. [Повторы через прокси: один потерянный ответ, две созданные задачи](/ru/blog/proxy-retries-duplicate-jobs) показывает этот случай и то, что меняет ключ идемпотентности.

Если для асинхронной работы вы используете HTTPX, смотрите [асинхронные прокси в HTTPX](/ru/guides/httpx-async-proxy). Для помощи с диагностикой внутри агента для написания кода [Proxy Toolkit MCP](/mcp) принимает очищенные описания ошибок. Не передавайте в его аргументах учётные данные.

## Как это проверялось

На Ubuntu 26.04.1 с Python 3.14.4 и OpenSSL 3.5.5, всё на `127.0.0.1`: `python -m http.server` в роли HTTP- и HTTPS-целей, прокси, который требует Basic-авторизацию и записывает каждый запрос с именами его заголовков, SOCKS5-сервер, который записывает каждое место назначения, и HTTPS-цель, которая сообщает полученные заголовки. Каждый из 67 случаев выполнялся в новом интерпретаторе с чистым окружением. Аккаунт прокси не использовался.

[Архив лаборатории](https://ipvolt.com/downloads/aiohttp-proxy-setup/aiohttp-proxy-lab.zip) содержит [скрипт запуска](https://ipvolt.com/downloads/aiohttp-proxy-setup/run_lab.py), [случаи](https://ipvolt.com/downloads/aiohttp-proxy-setup/cases.py), [прокси](https://ipvolt.com/downloads/aiohttp-proxy-setup/auth_proxy.py), [SOCKS5-сервер](https://ipvolt.com/downloads/aiohttp-proxy-setup/socks5_server.py), [README](https://ipvolt.com/downloads/aiohttp-proxy-setup/README.md) и [записанные результаты](https://ipvolt.com/downloads/aiohttp-proxy-setup/results.json).

Не проверялось: macOS и Windows, авторизация прокси по Digest и NTLM, SOCKS-прокси с авторизацией, запросы WebSocket, учётные данные из `~/.netrc` и прокси, до которых нужно подключаться по TLS.

ipvolt — прокси-сервис для разработчиков, который пока не открыт; [запишитесь в список раннего доступа](https://ipvolt.com/#waitlist-closing), и вы получите одно письмо, когда он откроется.

## Источники и дополнительное чтение

- [aiohttp changelog: 3.14.0](https://docs.aiohttp.org/en/stable/changes.html)
- [aiohttp pull request #12499: Deprecate auth. Add encode_basic_auth](https://github.com/aio-libs/aiohttp/pull/12499)
- [aiohttp Advanced Client Usage: proxy support and trust_env](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support)
- [aiohttp Client Reference: encode_basic_auth and proxy_headers](https://docs.aiohttp.org/en/stable/client_reference.html#aiohttp.encode_basic_auth)
- [aiohttp issue #4422: proxy_headers not passed to proxy](https://github.com/aio-libs/aiohttp/issues/4422)
- [aiohttp-socks on PyPI](https://pypi.org/project/aiohttp-socks/)
- [Python warnings: the default warning filter](https://docs.python.org/3/library/warnings.html#default-warning-filter)

## Связанные руководства

- [Как исправить ошибку прокси 407, не гадая](https://ipvolt.com/ru/guides/fix-proxy-error-407.md)
- [Переменные окружения прокси: HTTP_PROXY и NO_PROXY](https://ipvolt.com/ru/guides/proxy-environment-variables.md)
- [Асинхронные прокси в HTTPX: настройка и диагностика PoolTimeout](https://ipvolt.com/ru/guides/httpx-async-proxy.md)

## О ipvolt

Примеры используют обобщённые настройки прокси со ссылками на оригинальную техническую документацию. Поведение конкретного продукта уточняйте у своего провайдера. ipvolt пока в разработке.

[Читать оригинал на английском](https://ipvolt.com/guides/aiohttp-proxy-setup.md)

## Узнайте, когда откроется доступ.

ipvolt · В разработке

Мы строим прокси-инфраструктуру для разработчиков и команд, работающих с данными. Оставьте email, чтобы получить уведомление, когда ipvolt будет готов.

Одно письмо, когда откроется доступ. Больше ничего.

[Получить ранний доступ](https://ipvolt.com/ru/guides/aiohttp-proxy-setup#waitlist-closing)

[Конфиденциальность](https://ipvolt.com/privacy)

