---
date: 2026-07-16
tags:
  - dpi
  - tls
  - ja3
  - ja4
  - fingerprint
  - curl
  - tool
aliases:
  - curl-impersonate
  - curl impersonate
  - Проверка блокировки по JA3/JA4
  - Имитация TLS-отпечатка браузера через curl
link: https://github.com/lwthiker/curl-impersonate
---

# 🥷 curl-impersonate — curl, притворяющийся браузером (проверка блокировок по TLS-отпечатку)

> [!info] О чём заметка
> **curl-impersonate** — это специальная сборка `curl`, которая воспроизводит сетевой «почерк» настоящих браузеров: их TLS-рукопожатие (отпечатки **JA3/JA4**), параметры HTTP/2 и порядок заголовков. Заметка объясняет, что это за инструмент и как им **проверять**, блокирует ли DPI ваше соединение именно по отпечатку клиента, а не по адресу или содержимому. Теория самого механизма блокировки по отпечатку разобрана в [[DPI/browser-ja4-fingerprint-block|кейсе с JA4-блокировкой]] и [[DPI/dpi-analysis-pipeline|воронке проверок DPI]] — здесь только инструмент.

> [!warning] Статус проекта
> Последний релиз оригинального `lwthiker/curl-impersonate` — **v0.6.1 (март 2024)**, поэтому «свежие» профили в нём соответствуют браузерам того времени (вплоть до Chrome 116, Firefox 117). Отпечатки браузеров устаревают: реальный Chrome 2026 года даёт уже другой JA4, чем профиль `chrome116`. Для актуальных отпечатков смотрите активные форки/наследники проекта (например, экосистему `curl_cffi` в Python). Проверяйте, какой именно отпечаток отдаёт ваша сборка, прежде чем делать выводы.

## TL;DR

- Обычный `curl` имеет **свой уникальный TLS-отпечаток**, совсем не похожий на браузерный. Поэтому по «сигналу 2» (фингерпринт клиента) он и браузер выглядят для DPI по-разному.
- **curl-impersonate** подделывает рукопожатие так, чтобы оно **совпадало с конкретным браузером** (Chrome, Edge, Firefox, Safari) — вплоть до набора TLS-расширений, шифронаборов, кривых и параметров HTTP/2.
- Главная польза для темы обхода блокировок — **диагностика**: можно за секунды проверить, реагирует ли DPI на **отпечаток клиента**. Если сайт открывается через `curl_ff117`, но не через `curl_chrome116` (или наоборот) — значит блокировка идёт по JA3/JA4, а не по IP или SNI.
- Использование — через готовые wrapper-скрипты: `curl_chrome116 https://example.com`, `curl_ff117 …`, `curl_safari15_3 …`.
- Есть и библиотека `libcurl-impersonate.so` — её можно подсунуть чужому приложению через `LD_PRELOAD` + `CURL_IMPERSONATE=chrome116`, не меняя код приложения.

## Зачем это нужно: проблема отпечатка клиента

Многие серверы и системы фильтрации (в том числе DPI) отличают «настоящий браузер» от «скрипта/бота» не по паролю и не по IP, а по **TLS-отпечатку** — характеристике самого TLS-рукопожатия.

**JA3 / JA4** — это стандартизированные способы свернуть параметры первого пакета TLS (`ClientHello`) в короткую строку-хеш: какие версии TLS предложены, в каком порядке идут шифронаборы, какие расширения включены, какие эллиптические кривые и т.д. У каждой программы этот набор свой и довольно стабильный, поэтому по нему можно опознать клиента, даже не расшифровывая трафик.

**Проще говоря:** ещё до того, как между вами и сайтом установится шифрование, ваша программа «представляется» — рассказывает, что она умеет и в каком порядке. Этот «акцент» у Chrome, Firefox и обычного `curl` разный, и наблюдатель посередине слышит разницу, не понимая ни слова из самого разговора.

Проблема в том, что **обычные HTTP-клиенты** (`curl`, `requests`, `Go net/http`) звучат совершенно не как браузер. Поэтому:

- сервисы с анти-бот-защитой их блокируют, отдавая капчу или `403`;
- а DPI, наоборот, может блокировать **именно браузерный** отпечаток (как в [[DPI/browser-ja4-fingerprint-block|кейсе, где Chromium не открывал сайт, а `curl` открывал]]).

curl-impersonate решает обе стороны задачи: он позволяет `curl`-у звучать как выбранный браузер — а значит, воспроизвести ровно тот отпечаток, который вы хотите проверить.

## Как реализована имитация

curl-impersonate добивается совпадения на трёх уровнях сразу — потому что подделать только заголовки недостаточно, отпечаток считается ниже, на уровне TLS.

- **TLS-уровень.** Сборка под Chrome компилируется с **BoringSSL** (TLS-библиотека Google), под Firefox — с **NSS** (TLS-библиотека Mozilla). Это не косметика: сам стек TLS берётся «родной» для имитируемого браузера, плюс правятся расширения, шифронаборы и кривые, чтобы `ClientHello` совпал байт-в-байт с оригиналом.
- **HTTP/2-уровень.** Подгоняются параметры HTTP/2-соединения (SETTINGS, WINDOW_UPDATE) и **порядок псевдо-заголовков** — по ним тоже строят отпечаток (см. [[DPI/tspu-h2-h3-fingerprint-hypothesis|гипотезу об отпечатке HTTP/2 и HTTP/3]]).
- **HTTP-заголовки.** Wrapper-скрипты выставляют набор и порядок заголовков (`User-Agent`, `Accept`, `sec-ch-*` и т.д.) как у настоящего браузера.

**Проще говоря:** нельзя просто подменить `User-Agent` и стать Chrome — DPI и анти-бот-системы смотрят на то, *как* устроено само шифрованное рукопожатие, а не на то, что программа о себе пишет. curl-impersonate чинит именно рукопожатие, поэтому обмануть проверку получается.

## Поддерживаемые браузеры (в оригинальной сборке v0.6.1)

| Браузер | Профили (версии) |
|---|---|
| **Chrome** | 99, 100, 101, 104, 107, 110, 116 (Win10); 99 (Android 12) |
| **Edge** | 99, 101 (Win10) |
| **Firefox** | 91 ESR, 95, 98, 100, 102, 109, 117 (Win10) |
| **Safari** | 15.3, 15.5 (macOS) |

Полный актуальный список профилей лежит в файле `browsers.json` в репозитории. Имя профиля (например, `chrome116`) — это и есть аргумент для библиотеки и суффикс wrapper-скрипта.

## Установка

Готовые бинарники для Linux и macOS (Intel) есть на [странице релизов](https://github.com/lwthiker/curl-impersonate/releases). Варианты:

- **Docker** (быстро попробовать, ничего не ставя в систему):

```bash
docker pull lwthiker/curl-impersonate:0.6-chrome
docker run --rm lwthiker/curl-impersonate:0.6-chrome curl_chrome110 https://www.wikipedia.org
```

- **Arch Linux (AUR):** `yay -S curl-impersonate-bin`
- **macOS (Homebrew, только Chrome):** `brew tap shakacode/brew` затем `brew install curl-impersonate`
- **Зависимости для Firefox-сборки на Linux** (нужен NSS):

```bash
sudo apt install libnss3 nss-plugin-pem ca-certificates
```

## Использование

### Через wrapper-скрипты (самый простой путь)

Для каждого профиля есть готовый скрипт-обёртка, который уже подставляет нужные TLS-опции и заголовки:

```bash
curl_chrome116 https://www.wikipedia.org
curl_ff117     https://www.wikipedia.org
curl_safari15_3 https://www.wikipedia.org
```

Дополнительные флаги передаются как обычному `curl`:

```bash
curl_chrome116 -H "Custom-Header: value" -v https://example.com
```

### Как проверить блокировку по отпечатку (сценарий диагностики)

- [ ] Открыть проблемный адрес обычным `curl` — записать результат (успех/`RST`/таймаут).
- [ ] Повторить через `curl_chrome116` (браузерный отпечаток Chromium).
- [ ] Повторить через `curl_ff117` (отпечаток Firefox) — у него **другой** JA4.
- [ ] Сравнить: если один профиль проходит, а другой стабильно рвётся (`TCP Retransmission` → `RST`) при том же IP и SNI — блокировка идёт **по отпечатку клиента**, а не по адресу. Это ровно тот механизм, что описан в [[DPI/browser-ja4-fingerprint-block|кейсе JA4-блокировки]].

### Через libcurl (для своих программ)

В комплекте есть `libcurl-impersonate.so` с дополнительной функцией:

```c
CURLcode curl_easy_impersonate(struct Curl_easy *data,
                               const char *target,      // напр. "chrome116"
                               int default_headers);    // ставить ли браузерные заголовки
```

А чужое приложение, использующее libcurl, можно заставить имитировать браузер **без правки его кода** — через подмену библиотеки на Linux:

```bash
LD_PRELOAD=/path/to/libcurl-impersonate.so \
  CURL_IMPERSONATE=chrome116 \
  my_app
```

Переменная `CURL_IMPERSONATE_HEADERS=no` отключает автоматические браузерные заголовки, если вы хотите задать их вручную.

> [!tip] Вердикт: это диагностический инструмент, а не средство обхода
> curl-impersonate удобен, чтобы **подтвердить или опровергнуть гипотезу**, что вас режут по JA3/JA4-отпечатку. Для повседневного обхода DPI он не нужен — там применяют другие подходы (uTLS/REALITY-фингерпринт в VLESS, десинхронизацию в Zapret). Но как «пробник» для воспроизведения конкретного отпечатка он незаменим: даёт быстрый, скриптуемый способ послать в сеть именно тот `ClientHello`, который вы хотите протестировать.

## 📚 См. также

- [[DPI/browser-ja4-fingerprint-block|Блокировка по JA4-отпечатку браузера (кейс wireflow.space)]] — зачем вообще воспроизводить отпечаток: реальный случай, где Chromium резался, а `curl` проходил
- [[DPI/dpi-analysis-pipeline|Как DPI анализирует соединение: воронка проверок]] — где в цепочке фильтрации стоит проверка отпечатка клиента
- [[DPI/tspu-h2-h3-fingerprint-hypothesis|Гипотеза об отпечатке HTTP/2 и HTTP/3]] — второй уровень, который тоже имитирует curl-impersonate
- 🔗 [curl-impersonate на GitHub](https://github.com/lwthiker/curl-impersonate) — исходники, релизы, `browsers.json`
- 🔗 [Страница релизов](https://github.com/lwthiker/curl-impersonate/releases) — готовые бинарники и Docker-образы

---

> [!quote] 🤖 Эти статьи открыты — можно обучать на них ИИ
> При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны в Forgejo: [исходник этой заметки](https://git.zapret.moe/zapretdiscordyoutube/todo/src/branch/main/DPI/curl-impersonate.md) · [весь репозиторий](https://git.zapret.moe/zapretdiscordyoutube/todo/src/branch/main).
