HTTP-библиотеки: кто все эти ребята и почему они спорят у тебя в requirements.txt

HTTP-библиотеки: кто все эти ребята и почему они спорят у тебя в requirements.txt

Если ты когда-нибудь писал бекенд, интеграцию, Telegram-бота, парсер или что-то, что хоть раз делает GET в сторону чужого сервера, то ты уже живёшь в стране HTTP-библиотек. Она похожа на маленький городок: у каждого своя лавочка, свои заморочки, своя философия — и все уверены, что именно их способ отправить запрос «самый правильный».

Сегодня давай разберёмся, кто есть кто, почему у Python так много HTTP-клиентов, и какой выбрать под твой конкретный проект, чтобы потом не сидеть в три часа ночи и не материться на таймауты, deadlock-и и магические ошибки SSL.

И да, обещаю — без казённых фраз. Мы же не документацию пишем.

Зачем вообще нужен HTTP-клиент?

Вопрос вроде тупой, но...

Ты удивишься, сколько разработчиков делают HTTP-запросы каждый день, но плохо понимают, что там происходит под капотом.

Представь себе: ты открываешь браузер — он делает HTTP-запрос. Твой сервис стучится в Stripe — HTTP. Микросервис А вызывает микросервис Б — угадай что? Да, тоже HTTP.

HTTP-клиент — это не просто «послать запрос». Это:

  • корректно собрать URL
  • сформировать заголовки
  • закодировать body
  • уложиться в таймауты
  • переподключиться при обрыве
  • обработать 429, 500, 503
  • распарсить JSON
  • держать сессию
  • переподписать токен
  • иногда (когда зло и хаос) танцевать вокруг SSL

Теперь понимаешь, почему «простой» HTTP-клиент — это всё равно огромная машина?

Requests: дед, который до сих пор в форме

Давай начнём с легенды. Requests — это Python-эквивалент JavaScript-овского jQuery. Он не самый современный, не самый быстрый, но:

  • понятный
  • надёжный
  • до сих пор не умер

И главное — Requests придумал, как должны выглядеть «человеческие» HTTP-клиенты.

Код уровня:

import requests r = requests.get("https://api.example.com/data") print(r.json())

Видел даже человек, который Python знает на уровне «здравствуйте, мир».

Что внутри?

Requests использует:

  • urllib3 как движок
  • синхронную модель
  • классическую блокирующую архитектуру

То есть пока запрос выполняется — поток стоит.

Если у тебя бекенд обслуживает 10 запросов в секунду — норм. Если 10 000 — ну, брат, ты сам выбрал эту жизнь.

aiohttp: старейшина асинхронной мафии

Когда тебе нужно много запросов параллельно, но не хочется спавнить 400 потоков, приходит asyncio.

И тут на трон садится aiohttp.

Почему его любят?

  • быстрый
  • асинхронный
  • гибкий
  • умеет вебсокеты (да, это важно)

Код тоже приятный:

import aiohttp import asyncio async def main(): async with aiohttp.ClientSession() as session: async with session.get("https://api.example.com") as resp: print(await resp.json()) asyncio.run(main())

А теперь правда матка

aiohttp — классный, но у него есть нюансы:

  • API уже немного старомодное
  • документация иногда страдает
  • проект развивают медленнее, чем хотелось бы

Но если тебе нужно много параллельных запросов — aiohttp по-прежнему хорош.

HTTPX: тот самый «Requests, но нормально»

HTTPX — красавчик. Он сделал то, что многие мечтали:

  • единый API для sync + async
  • нормальная типизация
  • продуманная архитектура
  • отличная поддержка HTTP/2
  • middleware (!)
  • возможность подменять транспорт (для тестов — огонь)

Вот он — «Requests 2.0», который Requests сам никогда не выпустил.

API:

import httpx client = httpx.Client() r = client.get("https://api.example.com") print(r.json())

Async:

import httpx import asyncio async def main(): async with httpx.AsyncClient() as client: r = await client.get("https://api.example.com") print(r.json()) asyncio.run(main())

Когда HTTPX — идеальный выбор?

  • микросервисы
  • интеграции
  • высоконагруженные API-клиенты
  • когда нужен sync+async единым кодом
  • когда важен HTTP/2 (привет, gRPC-в-браузер-мире)

В 2025 году HTTPX — это реально новый стандарт.

urllib3: тот самый парень, который работает в тени

Это как движок BMW — никто не видит, но все знают, что он там. Requests держится на urllib3. HTTPX частично использует идеи urllib3.

Если ты хочешь делать свой HTTP-клиент — начнёшь ты именно с urllib3.

Это низкоуровневый, мощный, скучный и надёжный инструмент. Он нужен в библиотеках, но обычные разработчики туда почти не лезут.

http.client: «старый, но полезный»

Знаешь, как выглядит голый стандартный HTTP из Python stdlib?

Вот так:

import http.client conn = http.client.HTTPSConnection("example.com") conn.request("GET", "/") resp = conn.getresponse() print(resp.read())

Дёшево и сердито.

Но:

  • без cookies
  • без редиректов
  • без сессий
  • без таймаутов
  • без удобств

Это библиотека уровня «я пишу библиотеку для встраиваемых систем в 1997 году».

Тяжёлая артиллерия: Curl + PyCurl

Если тебе нужно максимальное управление HTTP:

  • тонкая настройка TLS
  • работа через прокси цепочки
  • сложные multipart-запросы
  • сумасшедшие требования к скорости

Ты берёшь Curl — и оборачиваешь его Python’ом через PyCurl.

Да, API выглядит как путешествие в ранние 2000-е:

import pycurl from io import BytesIO buffer = BytesIO() c = pycurl.Curl() c.setopt(c.URL, "https://example.com") c.setopt(c.WRITEDATA, buffer) c.perform() c.close() print(buffer.getvalue())

Но если ты пишешь систему интеграций для банка или какой-нибудь анти-fraud модуль — PyCurl будет тем ещё зверем.

А теперь самое вкусное: что выбрать?

Ладно, ты скажешь: «Чувак, красиво рассказываешь, но что брать в реальном проекте?»

Держи честный разбор.

1. Делал бота, парсер, интеграцию — Requests

Простой код, привычный API, понятность.

Только добавь таймауты:

requests.get(url, timeout=10)

Без таймаутов Requests превращается в маленькую бомбу замедленного действия.

2. Много запросов параллельно — aiohttp или HTTPX (async)

Тут всё зависит от вкуса:

  • хочешь проверенное временем → aiohttp
  • хочешь современное API и будущее → HTTPX Async

3. Универсальный клиент для всего проекта — HTTPX

Sync + async, middleware, HTTP/2. Ну реально, зачем страдать?

4. Нужен полный контроль над HTTP — PyCurl

Встречается редко, но раз в год и PyCurl стреляет.

5. Пишешь свою библиотеку — urllib3

Тут всё понятно.

Что нового в мире HTTP-клиентов в последние годы

Да, HTTP-библиотеки уже не просто «библиотеки». Это маленькие экосистемы.

HTTP/2 становится нормой

HTTPX уже поддерживает HTTP/2. Requests — нет и вряд ли будет. aiohttp — тоже умеет.

HTTP/2 нужен, когда:

  • много мелких запросов
  • стриминг
  • realtime логи
  • брокеры событий

Короче, жизнь меняется.

Async стал стандартом

Серьёзно, в 2025 писать синхронные API-клиенты — это как собирать сервер на systemd-shim. Работает, но как-то… странно.

Middleware повсюду

HTTPX перенёс в мир HTTP-клиентов нормальную идею middleware:

  • логирование
  • retry
  • refresh токена
  • proxy логики

Раньше это была боль.

Тестируемость!

HTTPX дал шикарную вещь — TestClient. Без моков, без танцев.

Настоящая проблема HTTP-клиентов — не клиенты, а таймауты и retry

Хочешь услышать правду? 95% проблем с HTTP не в том, какую библиотеку ты выбрал.

А в том, что у тебя:

  • нет таймаутов
  • нет retry
  • нет circuit breaker
  • нет логирования ошибок
  • нет graceful fallback

Без этого любой HTTP-клиент — просто красивая коробочка, внутри которой хаос.

Хочешь пример хорошей конфигурации HTTPX?

timeout = httpx.Timeout(10.0, connect=3.0) client = httpx.Client( timeout=timeout, limits=httpx.Limits( max_connections=100, max_keepalive_connections=20, ), transport=httpx.HTTPTransport(retries=5), )

И всё — у тебя API-клиент, который перестаёт быть «игрушкой».

Так какой итог?

HTTP-библиотек в Python много, но у каждой — своя точная роль. Главное — не относиться к ним как к магии. HTTP-клиент — это не «послать запрос», это инструмент, через который твой сервис общается с миром.

И чем круче твой инструмент, тем спокойнее твои ночи.

🙌 Если статья была полезной
Буду рад лайку и комментарию — это помогает продвигать материалы и показывает, что стоит разобрать в следующих публикациях.

1
Начать дискуссию