Рецепты

Рецепт - это один файл, который превращает один сайт в одну команду. Ваш агент запрашивает reddit/hot и получает структурированный JSON, а не хэндл браузера и задачу по парсингу.

npm install -g anti-detect-browser

anti-detect-browser recipe update
anti-detect-browser recipe run reddit/hot --temporary --json
anti-detect-browser recipe run reddit/hot --profile shopper-01 --jq '.items[].title'

Рецепты живут в отдельном публичном репозитории antibrow/recipes и общие для Node и Python SDK - один и тот же рецепт даёт одинаковый результат в обоих. Добавить сайт - это pull request туда, а не релиз SDK.

Это весь формат. Без импортов, без зависимостей, без сборки:

export const meta = {
  id: 'reddit/hot',
  summary: 'Hot posts from the front page or one subreddit.',
  domains: ['www.reddit.com'],      // все хосты, куда можно обращаться
  entry: 'https://www.reddit.com/', // страница, которую откроет рантайм
  identity: 'any',                  // 'any' | 'logged-in' | 'anonymous'
  args: [{ name: 'limit', type: 'number', default: 25, max: 100 }],
}

export async function run(ctx, args) {
  const res = await ctx.fetchJson(`/hot.json?limit=${args.limit}`)
  return { items: res.data.children.map((c) => ({ id: c.data.id, title: c.data.title })) }
}

run() выполняется внутри открытой страницы, поэтому относительный fetch несёт сессию этого профиля для этого сайта. Сайт без своего JSON-эндпоинта можно читать прямо из DOM.

В entry можно подставлять аргументы рецепта - https://www.google.com/search?q={query} - для страницы, которая существует только под конкретный запрос. Часть сайтов отдаёт результаты только на настоящую навигацию, а на fetch того же url отвечает редиректом, так что это разница между «дотянулись» и «нет». Хост не подставляется никогда: именно он проверяется по списку ниже.

Команды

Каждая команда принимает --json, а всё, что возвращает данные, принимает --jq: агент запрашивает два поля вместо целого ответа - .items[].title, .items[0], .items[1:3], length, keys, через |.

recipe update Забрать реестр и закрепить каждый рецепт по SHA-256.
recipe list [--site <site>] Что опубликовано. Непроверенные рецепты помечены.
recipe info <id> Аргументы, типы, значения по умолчанию, объявленные хосты, требование к личности, статус проверки.
recipe run <id> Запуск. Принимает --profile или --temporary, --args, --jq, --json, --headless, --timeout.
recipe fanout <id> --profiles <pattern> Запуск на нескольких профилях сразу, с --concurrency.
recipe test <id> Запустить локальную рабочую копию на временном профиле.
recipe scaffold <site>/<command> Создать заготовку по пути, который ожидает реестр.
recipe guide Напечатать руководство автора - себе или своему агенту.

В Python SDK тот же набор: python -m antibrow recipe ….

Fanout: одна команда на N личностей

Именно это недоступно инструменту, который управляет вашим обычным браузером. Одна команда, четыре профиля, четыре персоны, четыре набора cookie, четыре выходных IP:

anti-detect-browser recipe fanout reddit/hot \
  --profiles 'shopper-*' --concurrency 4 --json

Каждый профиль - отдельная личность, поэтому неудачная задача стоит профиля, а не аккаунта. Параллельность ограничена вашим тарифом и считывается до постановки в очередь: fanout не упирается в отказ на середине, что выглядело бы как сломанный рецепт. Падение одного профиля не роняет остальные - в результате видно, какой именно и почему.

Что рецепту разрешено

Рецепт - это код сообщества, который запускается в профиле с живыми логинами, поэтому к нему относятся как к расширению браузера:

meta.domains Проверяется на сетевом уровне, а не внутри помощников, которые предлагается использовать. Запрос к необъявленному хосту блокируется, поэтому рецепт для Reddit не доберётся до вашей почты. Заблокированные хосты возвращаются в результате - так же вы узнаёте, что новому рецепту ещё нужно объявить.
Пин по SHA-256 Каждый рецепт закреплён за теми байтами, которые эта машина увидела первыми. Если опубликованный файл изменился, следующий recipe update откажется работать, пока вы не прочитаете diff и не передадите --accept-changes.
Статус проверки По умолчанию запускаются только проверенные рецепты. --allow-unreviewed включает остальные, и только на --temporary профиле: такие профили локальные, поэтому собранное непроверенным рецептом не уезжает на другую машину.
Никаких записей Рецепты читают. Публикации, голосования, отправка и покупки вне области применения - как и последовательности кликов и ввода, управляющие интерфейсом.

Из агента (MCP)

Три инструмента, а не по одному на рецепт: список из сотни инструментов - это контекст, за который агент платит на каждом шаге. Остальное на странице MCP-сервера.

list_recipes
site?, query?
Что опубликовано: какие аргументы принимает каждый рецепт, к каким хостам обращается и проверен ли он.
run_recipe
id, args?, profile?, temporary?, jq?, allowUnreviewed?
Запустить один рецепт и получить JSON. temporary: true - анонимный запуск, profile - постоянная личность, которая остаётся авторизованной.
fanout_recipe
id, args?, profiles[], concurrency?, jq?
Запустить один рецепт сразу на нескольких профилях. Параллельность ограничена вашим тарифом.

Из кода

Node

import { runRecipe, fanoutRecipe } from 'anti-detect-browser'

const { value, blockedHosts } = await runRecipe({
  id: 'reddit/hot',
  key: process.env.ANTI_DETECT_BROWSER_KEY,
  temporary: true,
  args: { limit: 5 },
})

const { results } = await fanoutRecipe({
  id: 'reddit/hot',
  key: process.env.ANTI_DETECT_BROWSER_KEY,
  profiles: ['shopper-01', 'shopper-02', 'shopper-03'],
  concurrency: 3,
})

Python

from antibrow import run_recipe, fanout_recipe

result = run_recipe("reddit/hot", temporary=True, args={"limit": 5})
print(result.value, result.blocked_hosts)

fanned = fanout_recipe("reddit/hot", ["shopper-01", "shopper-02"], concurrency=2)
for row in fanned.rows:
    print(row.profile, row.value if row.ok else row.error)

Как написать свой

Рецепты - как раз та работа, которая хорошо получается у агента: открыть сайт, посмотреть сетевой лог, скопировать запрос с нужными данными, убрать зашитый токен, готово. Дайте ему руководство и не мешайте.

anti-detect-browser recipe guide
anti-detect-browser recipe scaffold mysite/list
anti-detect-browser recipe test mysite/list --args '{"limit":5}'

Изучайте сайт с одноразового профиля, а не со своего аккаунта - для этого и нужен --temporary, и это разница между потерянным профилем и потерянным аккаунтом. Затем открывайте pull request в antibrow/recipes: один сайт на один PR, точные хосты в meta.domains и вывод, который дал ваш тестовый запуск.