ИИ-агентам нужно ходить по настоящему вебу. Но настоящий веб враждебен к автоматизации: Playwright блокируют, headless-версия Chrome палится по отпечаткам, а стелс-плагины просто становятся частью отпечатка. Если вы когда-нибудь писали скраперы или инструменты для агентов, вы знаете, как это бывает - всё работает локально, а потом продакшен разваливается за Cloudflare-челленджем.Несколько проектов пытались решить эту проблему со стороны браузера. Проект https://camoufox.com патчит Firefox на уровне C++, так что navigator.hardwareConcurrency, WebGL-рендереры, AudioContext, геометрия экрана и WebRTC подменяются ещё до того, как JavaScript их увидит. Браузер https://github.com/jo-inc/camofox-browser оборачивает этот движок в REST API, заточенный под агентов: снимки доступности вместо раздутого HTML, стабильные ссылки на элементы для кликов и изоляция сессий.Остаётся только одна дыра: инструментарий вокруг этой экосистемы завязан на JavaScript/Python. Если вы живёте в Go - а весь стек Go-агентов, взорвавшийся за последние пару лет, весомый аргумент в его пользу - вам оставалось писать сырые вызовы curl.Пакет https://github.com/yvv4git/go-juggler исправляет это. Это Go-клиент для протокола автоматизации Juggler (того самого, который патчит и расширяет Camoufox) под лицензией MIT. Он управляет Firefox/Camoufox из Go с единственной зависимостью и чистым, слоистым API. Читать далее
ВступлениеИИ-агентам нужно ходить по настоящему вебу. Но настоящий веб враждебен к автоматизации: Playwright блокируют, headless-версия Chrome палится по отпечаткам, а стелс-плагины просто становятся частью отпечатка. Если вы когда-нибудь писали скраперы или инструменты для агентов, вы знаете, как это бывает - всё работает локально, а потом продакшен разваливается за Cloudflare-челленджем.
Несколько проектов пытались решить эту проблему со стороны браузера. Проект https://camoufox.com патчит Firefox на уровне C++, так что navigator.hardwareConcurrency, WebGL-рендереры, AudioContext, геометрия экрана и WebRTC подменяются ещё до того, как JavaScript их увидит. Браузер https://github.com/jo-inc/camofox-browser оборачивает этот движок в REST API, заточенный под агентов: снимки доступности вместо раздутого HTML, стабильные ссылки на элементы для кликов и изоляция сессий.
Остаётся только одна дыра: инструментарий вокруг этой экосистемы завязан на JavaScript/Python. Если вы живёте в Go - а весь стек Go-агентов, взорвавшийся за последние пару лет, весомый аргумент в его пользу - вам оставалось писать сырые вызовы curl.
Пакет https://github.com/yvv4git/go-juggler исправляет это. Это Go-клиент для протокола автоматизации Juggler (того самого, который патчит и расширяет Camoufox) под лицензией MIT. Он управляет Firefox/Camoufox из Go с единственной зависимостью и чистым, слоистым API.
Что такое JugglerJuggler - это протокол автоматизации браузера, разработанный для Firefox ещё до того, как в браузере появился CDP (Chrome DevTools Protocol). Репозиторий https://github.com/puppeteer/juggler принадлежит проекту Puppeteer. Это отдельный модуль внутри Firefox, а не часть ядра браузера, что упрощает его патчинг и контроль над тем, что раскрывается странице.
Проводной формат повторяет привычную CDP-раскладку:
{ "id": 1, "method": "Browser.newPage", "params": { ... } }
{ "id": 1, "result": { ... } }
{ "method": "Page.crashed", "params": { ... } }
Camoufox патчит Juggler, чтобы дать ему собственную изолированную "копию" страницы для работы. Playwright может свободно читать и редактировать свою версию, тогда как реальная страница остаётся нетронутой и не может обнаружить чтения, слушатели или внедрённых агентов. Ввод проходит через исходные обработчики ввода Firefox, поэтому клики и нажатия клавиш ведут себя точно как человеческие. Это та самая стелс-основа, на которой стоит go-juggler.
Что такое go-jugglerПакет go-juggler - это Go-клиент для протокола Juggler. Он автоматизирует браузеры с поддержкой Juggler, такие как Firefox и Camoufox, и предоставляет два способа управления ими:
1. Высокоуровневый REST-клиент (juggler.NewClient("http://localhost:9377")), который общается с запущенной HTTP-обёрткой camofox-browser - здесь сегодня живёт вся готовая к использованию магия.
2. Низкоуровневый слой транспорта и протокола (pipe и WebSocket-каналы с CDP-стилем фрейминга сообщений), который напрямую говорит на проводном протоколе Juggler - основа для запуска и подключения к процессу браузера внутри процесса.
Установка:
go get github.com/yvv4git/go-juggler
Быстрый старт
docker run -d -p 9377:9377 --name camoufox yvv4docker/camoufox:latest
Затем минимальная программа, проходящая весь жизненный цикл вкладки:
package main
package main
import (
"context"
"log"
"github.com/yvv4git/go-juggler"
)
func main() {
ctx := context.Background()
c := juggler.NewClient("http://localhost:9377")
tab, _ := c.OpenTab(ctx, "demo", "http://example.com")
snap, _ := c.Snapshot(ctx, tab.TabID, "demo")
c.Click(ctx, tab.TabID, "demo", "e1", "")
c.CloseTab(ctx, tab.TabID, "demo")
}Запуск полного примера жизненного цикла против живого экземпляра даёт вывод примерно такого вида:
health: ok=true engine=camoufox sessions=0
tab opened: 60bf9c8c-e6d9-4be0-ba09-738058215af6
navigated to rutube.ru
snapshot (128908 chars):
- img
- banner:
- button "Закрыть меню навигации" [e1]:
...
- button "Вход" [e9]
- navigation:
- list:
- listitem:
- link "Главная" [e10]:
tab closed
session closedМаркеры [e1], [e9], [e10] - это ключевая идея: снимок - это дерево доступности, где у каждого интерактивного элемента есть стабильная ссылка. Агенты находят и кликают элементы по ссылкам вместо борьбы с CSS-селекторами.
Health - проверить статус браузера (движок, соединение, память)
OpenTab - открыть новую вкладку и перейти по URL
Navigate - загрузить URL в существующей вкладке
Snapshot - получить ARIA-дерево страницы (ссылки на элементы)
Click - кликнуть по элементу по ссылке или CSS-селектору
Type - заполнить поле ввода по ссылке или селектору
Press - нажать клавишу клавиатуры (Enter, Tab, Escape и т.д.)
Scroll - прокрутить страницу вверх/вниз на N пикселей
Back - перейти назад по истории
Forward - перейти вперёд по истории
Refresh - перезагрузить текущую страницу
Links - вывести все ссылки на странице с пагинацией
Screenshot - сделать PNG-скриншот (страницы или вьюпорта)
Evaluate - выполнить произвольный JavaScript в контексте страницы
NetworkRequests - получить все загруженные ресурсы (навигация + подресурсы)
PollNetworkRequests - опрашивать ресурсы с течением времени с дедупликацией
Stats - получить состояние вкладки (URL, посещённые URL, ссылки)
ListTabs - вывести все вкладки в сессии (URL, заголовок)
CloseTab - закрыть вкладку
CloseSession - уничтожить всю сессию и все её вкладки
Три из них заслуживают более пристального взгляда.
Токен-эффективные снимкиВызов Snapshot возвращает ARIA-дерево доступности вместо сырого HTML. Это огромный выигрыш для LLM-агентов, где каждый байт стоит токенов: снимок доступности примерно на 90% меньше соответствующего HTML, и он уже структурирован по семантическим ролям (button, link, list item) с прикреплёнными ссылками.
Evaluate выполняет произвольный JavaScript в контексте страницы - удобно для разовых изменений, которые API не покрывает. Пример inject устанавливает заголовок документа и читает его обратно - проверяемый побочный эффект:
document.title = "Hi, friends!"; document.titleПримечание: эндпоинт /evaluate требует camofox-browser >= 1.4.0. Клиент обнаруживает более старый сервер (HTTP 404) и прямо сообщает вам об этом, а не молча падает.
NetworkRequests читает Performance API браузера и возвращает всё, что загрузила страница, это основной документ плюс подресурсы (CSS, скрипты, изображения, трекеры) - в хронологическом порядке. PollNetworkRequests расширяет это: он семплирует в течение заданного времени и объединяет результаты с дедупликацией, так что поздно загружающаяся реклама и трекеры аналитики тоже захватываются.
total requests: 6
1. [NAVIGATION ] https://www.wikipedia.org/
2. [CSS ] https://www.wikipedia.org/portal/wikipedia.org/assets/img/sprite-e49fbf32.svg
3. [SCRIPT ] https://www.wikipedia.org/portal/wikipedia.org/assets/js/index-34f340e24a.js
4. [SCRIPT ] https://www.wikipedia.org/portal/wikipedia.org/assets/js/gt-ie9-507b16b6be.js
5. [IMG ] https://www.wikipedia.org/portal/wikipedia.org/assets/img/Wikipedia-logo-v2.png
6. [IMG ] https://www.wikipedia.org/static/favicon/wikipedia.icoАрхитектура: три слоя, одно направлениеgo-juggler/
├── juggler.go # корневой пакет: публичный API-фасад
├── transport/ # байтовые каналы: pipe (fd 3/fd 4) и WebSocket
├── protocol/ # типы сообщений Juggler, JSON-кодирование/декодирование
├── browser/ # высокоуровневое управление браузером и вкладками
└── examples/ # запускаемые примеры программtransport/ перемещает сырые байты. Transport - это двунаправленный канал, передающий JSON, разбитый по строкам. Есть две реализации: PipeTransport, работающий через унаследованную пару OS-pipe (fd 3/fd 4, классическая внутрипроцессная схема для запущенного браузера), и WebSocketTransport, подключающийся к эндпоинту автоматизации браузера. Транспорты безопасны для конкурентного использования и уважают отмену контекста - блокирующее чтение прерывается, как только контекст завершён.
protocol/ придаёт этим байтам смысл. Он определяет тип Message (id / method / params / result / error), трёхстороннюю классификацию (IsRequest, IsResponse, IsEvent) и JSON-хелперы кодирования/декодирования. Этот пакет остаётся независимым от любого транспорта.
browser/ - высокоуровневая поверхность. Browser оборачивает транспорт с насосом сообщений, чтобы вызывающие работали с типизированными хендлами вместо сырого JSON. Client - HTTP-клиент для REST API camofox-browser. Launcher - место, где реальный процесс браузера порождается и подключается.
Зависимости текут в одну сторону, сверху вниз: browser/ импортирует transport/, а protocol/ остаётся независимым. Корневой пакет реэкспортирует API браузера, так что большинству вызывающих достаточно одного импорта:
import "github.com/yvv4git/go-juggler"Примеры программexamples/basic - полный жизненный цикл вкладки (health, open, navigate, snapshot, close).
examples/tab - все 16 операций с вкладками в одной программе: open, snapshot, links, stats, evaluate, click, navigate, back, forward, type, press, scroll, refresh, screenshot, close.
examples/inject - инъекция JavaScript через Evaluate.
examples/requests - сопутствующий захват сетевых запросов с опросом и дедупликацией.
examples/screen - скриншоты вьюпорта и полной страницы в PNG.
examples/html - HTML страницы до и после загрузки динамического контента.
Пример с несколькими вкладками показывает, как масштабируются сессии:
opened 1: http://example.com/
opened 2: http://example.org/
opened 3: http://example.net/
total tabs: 3
1. [Example Domain] http://example.com/
2. [Example Domain] http://example.org/
3. [Example Domain] http://example.net/
closed acd74c0c
closed 8c0951ac
closed 57adc6dd
session closedСтатусgo-juggler находится в активной разработке, и стоит чётко сказать, что сделано, а что нет.
Работает сегодня: полный HTTP REST-клиент для camofox-browser (все девятнадцать методов выше), слой транспорта (pipe + WebSocket с фреймингом, учитывающим контекст), типы сообщений протокола и все шесть примеров программ.
В дорожной карте: прямой путь - browser.Launch, порождающий исполняемый файл Camoufox с унаследованными pipe-fd и подключающийся по сырому протоколу Juggler, плюс полный API насоса сообщений Browser/Tab (navigate, reload, события страницы). Всё это помечено как TODO в исходниках и появится по мере завершения низкоуровневой поверхности протокола.
Если ваш сценарий - управление экземпляром Camoufox через REST API camofox-browser сегодня, go-juggler готов. Если вам нужно внутрипроцессное запускание браузера по сырым pipe - оно на подходе.
ИтогиЭкосистема автоматизации антидетект-браузеров слишком долго была историей про JavaScript. go-juggler приносит те же стелс-возможности - подмену отпечатков на уровне C++, токен-эффективные ARIA-снимки, стабильные ссылки на элементы, изоляцию сессий - в экосистему Go с одним импортом и почти пустым деревом зависимостей.
Ссылки:
go-juggler on GitHub https://github.com/yvv4git/go-juggler
Juggler Protocol Architecture https://deepwiki.com/daijro/camoufox/6.1-juggler-system)
Camoufox https://camoufox.com
camofox-browser https://github.com/jo-inc/camofox-browser
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Вторая копия Vue: как лишняя строка в lockfile повесила Chromium | 0 | 6.77 | 09-08-2026 |
| 2 | ИИ-агент двойного назначения | 0 | 13.15 | 29-05-2026 |
| 3 | Продакшн‑разработка в одиночку с AI‑агентами: принуждай к правилам, а не объясняй их | 0 | 8.25 | 24-07-2026 |
| 4 | Оптимизация без AI: как я автоматизировал API-ручки и типы | -2 | 5 | 29-06-2026 |
| 5 | [Перевод] Пишем движок для JavaScript с нуля | 0 | 6.36 | 09-06-2026 |
| 6 | Дизайн сайта с управлением жестами без Фигмы: как остаться автором, когда руки — ИИ | 0 | 11.88 | 18-07-2026 |
| 7 | Query‑first подход или как из SQL запросов или MongoDB контрактов получить готовое REST API | 5 | 7 | 06-07-2026 |
| 8 | Пишем логи в journald с помощью Logback и FFM API | -1 | 7.89 | 10-08-2026 |
| 9 | Один интерфейс — девять LLM-провайдеров: как мы подружили Kimi K3, GLM-5.2, Claude и Ollama в одном терминальном агенте | 0 | 12.65 | 31-07-2026 |
| 10 | Playwright не спасает от флапающих тестов: разбираемся, как он ждёт на самом деле | 0 | 8.65 | 24-07-2026 |