Afina

Скачать приложение

AppleWindows
RU
БлогБлог

15 мая 2026 г.

API Afina: автоматизация антидетект-браузера через REST

API Afina: автоматизация антидетект-браузера через REST

Один POST-запрос - и у вас уже создано 100 профилей с уникальными отпечатками, привязанными прокси и поднятыми браузерами в режиме headless или с CDP-эндпоинтом для Puppeteer. Никаких облачных лимитов, токенов на тарифах и API-rate-limit-ов: API Afina полностью локальный, работает на 127.0.0.1:50778, и единственный, кто решает, сколько вы делаете запросов - это ваша машина.

В этой статье разбираем, как устроен API антидетект-браузера Afina: 79 endpoint-ов, схема авторизации, как поднять первый профиль и подцепить к нему Puppeteer или Playwright за 5 минут, какие сценарии перестают быть болью при переходе с UI на API, и где проходит граница между REST API и MCP-сервером для тех, кто думает "что выбрать".

Зачем нужен API антидетект-браузера

Если вы работаете с мультиаккаунтингом на сотнях профилей, рутина в UI быстро становится ограничивающим фактором:

  • Аффилиатный маркетинг. Создание 200 профилей под кампанию руками - два часа. Через API - один цикл с for и 30 секунд работы.
  • Фарминг аккаунтов. Подготовка профилей по геолокациям с проксями, тегами и автологинами. Прокси с ротацией, прогрев - всё это не существует без скриптинга.
  • Веб-скрапинг. Параллельный сбор данных с десятков сайтов - каждый профиль свой fingerprint, своя cookie-jar, своя прокся. UI на это не рассчитан.
  • E-commerce и мониторинг конкурентов. Цены, описания, акции - собирать вручную невозможно, через API - ровно столько, сколько ваша инфраструктура потянет.
  • Bonus hunting и airdrop-кампании. Сложные расписания запусков с распределением во времени для обхода антифрод-кластеризации - это всё API + cron.
  • Ставки и арбитраж. Скорость реакции в секундах, синхронные действия на десятках профилей. Только программный путь.

Если вы делаете что-то одно и то же больше двух раз - это уже задача для API. Afina даёт REST-интерфейс, который покрывает 100% возможностей UI - всё, что вы можете кликнуть, можно вызвать одним HTTP-запросом.

Чем API Afina отличается от облачных аналогов

Большинство антидетект-браузеров (Octo, Multilogin, Dolphin) предоставляют облачные API - ваши запросы идут на сервер вендора, проходят квоту по тарифу, и оттуда уже доводятся до локального приложения. У такого подхода есть обратная сторона:

  • Лимиты по подписке. 1000-5000 запросов в сутки на старших тарифах - для серьёзной автоматизации этого мало.
  • Сетевая задержка. Каждый вызов идёт через интернет дважды - до облака и обратно к локальному клиенту.
  • Привязка к доступности облака. Упал сервер вендора - упала вся ваша автоматизация, даже если своё железо работает.
  • Передача данных за пределы машины. Что бы вендор ни обещал, метаданные ваших профилей и параметров запросов уходят в их инфраструктуру.

API Afina устроен иначе: это локальный HTTP-сервер на 127.0.0.1, который запускается вместе с десктоп-приложением. Никаких облачных посредников, никаких rate-лимитов, никакой задержки выше миллисекунд. Запрос идёт прямо в Rust-бэкенд приложения, который и так выполняет всю работу - API просто открывает к нему второй канал.

ПараметрОблачный API (Octo и пр.)Локальный API Afina
Лимит запросов в деньПо подписке (1k-10k)Не ограничен
Latency50-300 мс1-10 мс
Зависит от облака вендораДаНет
Данные уходят за пределы машиныДаНет
Работает offlineНетДа (для локальных операций)
СтоимостьПо тарифуБесплатно
Прямой доступ к CDPНет, только команды-обёрткиДа, wsEndpoint отдаётся в ответе

Эта разница принципиально меняет архитектуру решений. Вы можете гонять десятки тысяч вызовов в час без оглядки на квоты, держать боты в локальной сети без выхода в интернет (для всего, что не требует внешних сервисов), и подключаться напрямую к Chrome DevTools Protocol для самых тонких сценариев.

5 минут на старт

Шаг 1. Получить API-ключ

Запустите Afina, откройте Настройки -> API и скопируйте ключ. Это строка из 32 символов [A-Za-z0-9], которая генерируется автоматически при первом запуске и хранится зашифрованной (libsodium sealed-box) в локальной базе.

Ключ передаётся в заголовке X-API-Key каждого запроса. Без валидного ключа сервер силентно закрывает соединение - без ответа и без HTTP-кода. Это сделано намеренно: атакующий не получает информации о причине отказа и не может отличить "неправильный ключ" от "сервер не отвечает".

Шаг 2. Проверить, что сервер живой

curl http://127.0.0.1:50778/api/health

Ответ:

{ "status": "ok", "version": "2.0.4" }

Если получили Connection refused - Afina не запущена. Здоровья не требуется передавать ключ.

Шаг 3. Получить список профилей

curl http://127.0.0.1:50778/api/profiles/list \
  -H "X-API-Key: ВАШ_КЛЮЧ"

Ответ:

{
  "data": [
    { "accountId": "550e8400-...", "name": "Profile 1", "tags": ["test"], "isRunning": false },
    { "accountId": "660e8400-...", "name": "Profile 2", "tags": ["prod"], "isRunning": true }
  ],
  "count": 2
}

Если этот вызов прошёл - у вас всё работает. Дальше уже только дело фантазии.

Анатомия API: 79 endpoint-ов по категориям

Все эндпоинты сгруппированы по доменам сущностей. Базовый URL - http://127.0.0.1:50778, все принимают Content-Type: application/json и заголовок X-API-Key. Полный список ниже.

Профили (аккаунты) - 10 эндпоинтов

PathMethodНазначение
/api/profiles/listGETВсе аккаунты с фильтрами по тегам/группам
/api/profiles/getGET, POSTОдин аккаунт по ID или UUID
/api/profiles/createPOSTСоздать постоянный профиль
/api/profiles/one-timePOSTСоздать одноразовый (auto-delete на стопе)
/api/profiles/updatePOSTОбновить параметры
/api/profiles/startPOSTЗапустить браузер -> возвращает wsEndpoint для CDP
/api/profiles/stopPOSTОстановить (graceful shutdown с дописыванием cookies)
/api/profiles/deletePOSTSoft-delete (в корзину, восстановимо)
/api/profiles/hard-deletePOSTОкончательное удаление с очисткой данных
/api/profiles/cookies/set, /cookies/exportPOSTИмпорт/экспорт cookie-jar

При создании профиля все параметры идут одним JSON - прокси, теги, группы, экран, языки, шумы фингерпринта, стартовые URL, заблокированные порты, extraArgs, settings. Уникальный fingerprint (user agent, WebGL renderer, CPU/memory, fonts, time zone) генерируется тем же бэкендом, что использует UI - это не "случайные значения", а валидные комбинации, которые проходят даже сложные проверки фингерпринта.

Soft-delete и hard-delete разделены намеренно: первый кладёт профиль в корзину (восстанавливается одним кликом или вызовом), второй удаляет всё - включая папку с профилем, cookies, кэш и токен в keychain. Запущенный браузер при hard-delete стопится gracefully, без потери данных.

Управление браузером (CDP-команды) - 5 эндпоинтов

PathMethodНазначение
/api/profiles/evalPOSTВыполнить JavaScript в текущей вкладке
/api/profiles/screenshotPOSTСкриншот страницы -> base64 PNG
/api/profiles/cookies/setPOSTУстановить cookie через CDP Network.setCookies
/api/profiles/cookies/exportPOSTПрочитать все cookie через CDP

Это инструменты "быстрого касания" - для одноразовых операций без полноценного скрипта. Для серьёзной автоматизации (заполнение форм, навигация, ожидание элементов) лучше использовать Puppeteer/Playwright через wsEndpoint - про это ниже.

eval принимает JavaScript-выражение, выполняет его в контексте активной страницы, авто-await промисов, returnByValue. Можно вернуть строку, число, объект - всё, что сериализуется в JSON.

RPA-скрипты - 7 эндпоинтов

PathMethodНазначение
/api/scripts/listGETВсе RPA-скрипты
/api/scripts/getGETОдин скрипт по ID
/api/scripts/createPOSTСоздать RPA-скрипт (JSON блоков)
/api/scripts/updatePOSTОбновить
/api/scripts/runPOSTЗапустить скрипт на профиле -> task_uuid
/api/scripts/run-logsGETЛоги прямого запуска
/api/scripts/stopPOSTОстановить выполнение

RPA-скрипты Afina - это JSON-структура с блоками (click, type, goto, condition, loop, executeModule и т.д.) и связями между ними. Каждый блок описывает шаг сценария, executor выполняет их по графу.

Для автоматического создания скриптов из своего кода - передайте полный JSON с массивами elements и connections в /api/scripts/create. Структура совпадает с тем, что видит визуальный конструктор, и любой созданный через API скрипт можно открыть и редактировать в UI.

RPA-модули - 7 эндпоинтов

PathMethodНазначение
/api/modules/listGETВсе модули
/api/modules/getGETОдин модуль + список файлов
/api/modules/createPOSTСкаффолд (index.js, utils_<id>.js, package.json, settings.json) + npm install
/api/modules/updatePOSTОбновить файлы или метаданные
/api/modules/resignPOSTПересчитать Ed25519-подпись
/api/modules/deletePOSTSoft-delete
/api/modules/hard-deletePOSTОкончательное удаление

Когда визуальных RPA-блоков не хватает - пишется кастомный JavaScript-модуль. Через API всё делается end-to-end: создание (с автоматической npm install для зависимостей), правка файлов, переподпись.

Важная деталь: каждый модуль подписан Ed25519 поверх MD5-манифеста папки. Любое изменение файлов без вызова resign ломает подпись - executor блокирует запуск с понятной ошибкой. Это защита от подмены кода: вы не запустите модуль, который кто-то поменял за вашей спиной.

Группы задач и задачи - 17 эндпоинтов

PathMethodНазначение
/api/task-groups/listGETСписок групп
/api/task-groups/getGETГруппа со своими задачами
/api/task-groups/tasksGETТолько задачи группы
/api/task-groups/createPOSTСоздать группу с расписанием
/api/task-groups/updatePOSTОбновить расписание/название
/api/task-groups/startPOSTАктивировать (active=1)
/api/task-groups/stopPOSTДеактивировать + остановить running-задачи
/api/task-groups/restartPOSTПерезапустить error/finished задачи
/api/task-groups/deleteDELETE, POSTSoft-delete
/api/task-groups/hard-deletePOSTОкончательное удаление
/api/tasks/listGETВсе задачи (фильтры по status, scriptId)
/api/tasks/activeGETТолько выполняемые сейчас
/api/tasks/logsGETЛоги по task_uuid
/api/tasks/createPOSTДобавить задачи в группу (bulk)
/api/tasks/updatePOSTИзменить статус/executeAt/тег
/api/tasks/deletePOSTSoft-delete (массово)
/api/tasks/stopPOSTОстановить выполнение (с опцией closeBrowser)

Это самая мощная категория API. Группа - это конфигурация расписания (окна времени, повторы, таймауты, лимит параллелизма), задача - единичный запуск скрипта на конкретном аккаунте.

Расписание поддерживает естественные форматы дат для поля executeAt:

  • "now" - сразу
  • "in 5m" - через 5 минут
  • "+1h" - через час
  • "tomorrow 09:00" - завтра в 9:00 локального времени
  • "2026-05-15 14:30" - конкретный момент
  • ISO 8601: "2026-05-15T14:30:00Z"
  • Unix epoch: 1715787000

Окна времени и параллелизм задаются на уровне группы:

{
  "schedule": true,
  "timeFrom": "09:00",
  "timeTo": "18:00",
  "scheduleTime": true,
  "startHour": 9.0,
  "endHour": 18.0,
  "activeSession": 5,
  "isRepeatable": true,
  "repeatCount": 2,
  "timeout": 300
}

Группа будет запускать максимум 5 задач параллельно, только в окне 09:00-18:00, повторит каждую дополнительно 2 раза, и каждая задача автоматически таймаутится через 5 минут. Это конфигурация для серьёзных продакшен-кампаний - обычно для UI это 10 минут кликов, а через API - один POST.

Прокси - 3 эндпоинта

PathMethodНазначение
/api/proxies/addPOSTДобавить и проверить
/api/proxies/checkPOSTПроверка одного/нескольких
/api/proxies/check-allPOSTАудит всех в таблице

Все проверки делаются с реальным сетевым тестом, включая UDP-тест для SOCKS5 (критично, потому что Afina поддерживает HTTP/3 поверх SOCKS5 с QUIC). Прокси, которые не прошли - не сохраняются. Это даёт уверенность, что в базе только живые соединения.

Подробнее про типы и сценарии прокси - в материале про прокси и их виды.

Базы данных, переменные, ключи - 15 эндпоинтов

PathMethodНазначение
/api/databases/*GET/POSTCRUD подключений (SQLite/MySQL/PostgreSQL) для RPA-блока database
/api/global-vars/*GET/POSTCRUD глобальных переменных ${name}, доступных во всех скриптах
/api/keys/*GET/POSTКаталог ключей и API-токенов (OpenAI, Telegram, ChatGPT)
/api/accounts/varsGETВсе переменные аккаунта (plain + encrypted)
/api/accounts/vars/setPOSTЗаписать (plain или encrypted)
/api/accounts/vars/deletePOSTУдалить

Особое внимание - на account_vars. Они хранятся в двух режимах:

ХранилищеГдеВидно по API
Plainaccount.settingsДа
Encryptedaccount_data_blobНет (только запись и чтение по ключу)

Encrypted-переменные шифруются sealed-box (libsodium). Через API можно записать значение и потом прочитать по тому же ключу - но сам plaintext по API никогда не отдаётся. Расшифровка происходит только в executor-е скрипта прямо перед выполнением. Это идеальное хранилище для 2FA-секретов, паролей и приватных ключей крипто-кошельков.

Email / IMAP - 2 эндпоинта

PathMethodНазначение
/api/emails/listGETСписок настроенных email-адресов
/api/emails/togglePOSTВкл/выкл мониторинг IMAP

Управление IMAP-подключениями для автоматического разбора писем (коды подтверждения, ссылки восстановления, внутренние нотификации).

Выбор языка: Node, Python или что-то ещё

API Afina - это обычный HTTP+JSON. Ему всё равно, чем вы делаете запросы. Самые ходовые варианты:

ЯзыкКогда использоватьРекомендуемые библиотеки
Node.jsЕсли уже работаете с Puppeteer/Playwright (они тоже Node)axios, node-fetch, undici
PythonДата-сайнс, парсинг, ML-обвязкаrequests, httpx, aiohttp
GoВысоконагруженные параллельные обработкистандартная net/http
Bash + curlСкрипты деплоя, оркестрация, CIcurl + jq
PHP, Ruby, C#, JavaПод существующий стек командылюбая HTTP-библиотека

Если код есть на одном языке, а нужно перевести на другой - попросите ChatGPT или Claude. С обычным REST это работает безотказно. Структура одна и та же: URL, метод, заголовок X-API-Key, JSON-тело.

Под Puppeteer/Playwright/Selenium всё равно потребуется Node или Python - они нужны не для API Afina, а для управления самим браузером после start_browser. Эти три инструмента - стандарт индустрии для автоматизации на CDP/WebDriver, и Afina с ними дружит из коробки.

Связка с Puppeteer и Playwright через wsEndpoint

Самая мощная фишка API Afina - прямой доступ к Chrome DevTools Protocol. Когда вы запускаете профиль через /api/profiles/start, в ответе приходит wsEndpoint - это полноценный CDP WebSocket, к которому можно подцепить любой инструмент.

Пример на Node.js + Puppeteer

import axios from 'axios';
import puppeteer from 'puppeteer';

const API = 'http://127.0.0.1:50778';
const KEY = process.env.AFINA_API_KEY;
const headers = { 'X-API-Key': KEY };

async function main() {
  // 1. Запускаем профиль через API Afina
  const { data } = await axios.post(
    `${API}/api/profiles/start`,
    { profileId: '550e8400-e29b-41d4-a716-446655440000' },
    { headers }
  );

  console.log('Browser started, CDP:', data.wsEndpoint);

  // 2. Подключаем Puppeteer к существующему браузеру
  const browser = await puppeteer.connect({
    browserWSEndpoint: data.wsEndpoint,
    defaultViewport: null,
  });

  // 3. Дальше  -  обычный Puppeteer
  const page = (await browser.pages())[0] || await browser.newPage();
  await page.goto('https://example.com');
  await page.waitForSelector('h1');
  const title = await page.$eval('h1', el => el.innerText);
  console.log('H1:', title);

  // 4. Отключаемся (браузер остаётся запущенным)
  await browser.disconnect();

  // 5. Закрываем профиль через API
  await axios.post(`${API}/api/profiles/stop`,
    { profileId: '550e8400-e29b-41d4-a716-446655440000' },
    { headers }
  );
}

main().catch(console.error);

Пример на Python + Playwright

import os
import requests
from playwright.sync_api import sync_playwright

API = 'http://127.0.0.1:50778'
KEY = os.environ['AFINA_API_KEY']
HEADERS = {'X-API-Key': KEY}

profile_id = '550e8400-e29b-41d4-a716-446655440000'

# 1. Запускаем профиль
resp = requests.post(
    f'{API}/api/profiles/start',
    json={'profileId': profile_id},
    headers=HEADERS,
).json()
ws = resp['wsEndpoint']
print('CDP:', ws)

# 2. Playwright connect
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(ws)
    context = browser.contexts[0]
    page = context.pages[0] if context.pages else context.new_page()
    page.goto('https://example.com')
    print('Title:', page.title())
    browser.close()

# 3. Закрываем профиль
requests.post(
    f'{API}/api/profiles/stop',
    json={'profileId': profile_id},
    headers=HEADERS,
)

Selenium WebDriver

Selenium тоже работает - через chromedriver с флагом --remote-debugging-port. Чуть менее удобно (требует дополнительной настройки), но для legacy-проектов - рабочая опция. Подробности в гайде по автоматизации действий в браузере.

Готовые рецепты для типовых сценариев

Рецепт 1. Создать 100 профилей с прокси за минуту

import axios from 'axios';
const API = 'http://127.0.0.1:50778';
const headers = { 'X-API-Key': process.env.AFINA_API_KEY };

const proxies = JSON.parse(await fs.readFile('proxies.json', 'utf8'));

for (let i = 0; i < 100; i++) {
  await axios.post(`${API}/api/profiles/create`, {
    name: `Campaign-1 #${i + 1}`,
    tags: ['campaign-1', 'phase-1'],
    proxy: proxies[i % proxies.length],
    settings: {
      languages: ['en-US', 'en'],
      startupURLs: ['https://example.com/landing'],
    },
  }, { headers });
}

100 профилей с уникальными отпечатками, привязанными прокси и тегами - готовы к запуску через минуту. То же самое в UI заняло бы час.

Рецепт 2. Bulk-запуск скрипта на 50 аккаунтах с расписанием

// 1. Создаём группу с расписанием
const group = (await axios.post(`${API}/api/task-groups/create`, {
  tag: 'warmup-batch-1',
  active: false,
  schedule: true,
  timeFrom: '09:00',
  timeTo: '18:00',
  activeSession: 5,
  isRepeatable: false,
}, { headers })).data;

// 2. Получаем список аккаунтов с тегом
const accounts = (await axios.get(
  `${API}/api/profiles/list?tag=campaign-1`, { headers }
)).data.data;

// 3. Добавляем задачу для каждого с разносом во времени
const tasks = accounts.map((acc, i) => ({
  accountId: acc.accountId,
  scriptId: 42,
  executeAt: `+${i * 3}m`,
}));

await axios.post(`${API}/api/tasks/create`, {
  groupId: group.id,
  tasks,
}, { headers });

// 4. Запускаем группу
await axios.post(`${API}/api/task-groups/start`,
  { id: group.id }, { headers });

Прогрев 50 аккаунтов с интервалом 3 минуты, в окне 09:00-18:00, максимум 5 параллельно - один файл, 30 строк кода, ровно один запуск.

Рецепт 3. Получить логи всех упавших задач за день

curl "http://127.0.0.1:50778/api/tasks/list?status=error&since=2026-05-14T00:00:00Z" \
  -H "X-API-Key: $AFINA_API_KEY" \
  | jq -r '.data[] | .taskUuid' \
  | while read uuid; do
      echo "=== $uuid ==="
      curl -s "http://127.0.0.1:50778/api/tasks/logs?uuid=$uuid" \
        -H "X-API-Key: $AFINA_API_KEY" \
        | jq -r '.data[] | "\(.time) [\(.level)] \(.message)"'
    done

Все ошибки за день в один отчёт. Можно скармливать LLM или парсить регулярками для разметки причин падений.

Рецепт 4. Eval JavaScript на запущенном браузере

curl -X POST http://127.0.0.1:50778/api/profiles/eval \
  -H "X-API-Key: $AFINA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profileId": "550e8400-...",
    "code": "JSON.stringify({ url: location.href, title: document.title, cookies: document.cookie })"
  }'

Ответ:

{
  "result": "{\"url\":\"https://example.com\",\"title\":\"Example Domain\",\"cookies\":\"\"}"
}

Промежуточный вариант между ничем и полноценным Puppeteer - для быстрых проверок и пробинга страниц.

Рецепт 5. Бэкап cookie всех профилей с тегом

import requests, json, os

API = 'http://127.0.0.1:50778'
H = {'X-API-Key': os.environ['AFINA_API_KEY']}

accounts = requests.get(f'{API}/api/profiles/list?tag=prod', headers=H).json()['data']

for a in accounts:
    cookies = requests.post(
        f'{API}/api/profiles/cookies/export',
        json={'profileId': a['accountId']},
        headers=H,
    ).json()
    with open(f'backup/{a["accountId"]}.json', 'w') as f:
        json.dump(cookies, f)

Полный бэкап cookie-jars всех продакшен-профилей - под каждый чих CI/CD, после крупного апдейта или просто как страховка.

Безопасность

API Afina проектировался с учётом, что любая локальная поверхность атаки - это поверхность атаки. Что сделано:

  • Только localhost. Сервер биндится только на 127.0.0.1. С внешней сети до него не достучаться даже теоретически. Если нужен удалённый доступ - делайте через SSH-tunnel (ssh -L 50778:127.0.0.1:50778 user@host) и сами решайте, кому даёте доступ к туннелю.
  • API-ключ в каждом запросе. Без X-API-Key сервер дропает соединение силентно, без HTTP-ответа. Атакующий не может определить, рабочий ли там сервер вообще, не говоря про брутфорс ключей.
  • Encrypted account vars. Чувствительные данные (2FA, пароли, seed-фразы) шифруются sealed-box и не отдаются по API в plaintext. Доступ к ним есть только у RPA-executor-а в момент запуска скрипта.
  • Подписанные модули. Любой кастомный JS-модуль подписан Ed25519. Подмена файлов без resign ломает подпись - executor блокирует запуск. Это защищает от сценариев "кто-то получил доступ к диску и подменил index.js".
  • Изоляция профилей. Базовая фича Afina, не специфичная для API: каждый профиль - своя cookie-jar, localStorage, IndexedDB, кэш. Подключение API не размывает эту изоляцию.
  • Лимит соединений. 128 одновременных запросов одновременно - защита от случайного DoS со стороны вашего же кода.
  • Лимит размера запроса. 16 МБ на запрос - отрезает атаки через гигантские payload-ы.

API или MCP: что выбрать

У Afina есть MCP-сервер - это отдельный продукт, тонкая обёртка поверх REST API, которая отдаёт те же возможности AI-агентам (Claude, ChatGPT, Cursor) через Model Context Protocol. Возникает резонный вопрос: что использовать - MCP или прямой API?

КритерийПрямой REST APIMCP-сервер
Кто пользовательРазработчик с кодомAI-агент или человек в чате
Контроль над логикойПолныйЧерез промпт
Скорость разработкиМедленнее (надо писать код)Мгновенно (фраза в чате)
Воспроизводимость100% (код детерминирован)Зависит от модели
Подходит для CI/CDДаНет (нет AI в пайплайне)
Интеграция в существующий кодИдеальноНе предназначен
Уровень абстракцииEndpoint-уровеньНамерения уровня "сделай X"

Берите REST API, если:

  • У вас есть команда и кодовая база, в которую интеграция Afina - один из модулей.
  • Нужна полная воспроизводимость и контроль (CI/CD, регулярные джобы, прод-кампании).
  • Хочется обернуть API в свой UI или API gateway.

Берите MCP, если:

  • Вы в чате с Claude/ChatGPT и хотите "просто говорить, что нужно".
  • Прототипируете идеи, исследуете возможности.
  • Команда без программистов, но AI-агент уже под рукой.

В большинстве серьёзных команд используются оба: MCP - для рисёрча и быстрых проб, REST API - для прода.

Antidetect-браузер без API - это инструмент для одиночек. UI хорош, пока вы делаете десятки операций. На сотнях он замедляет, на тысячах - становится невозможным.

API превращает Afina в платформу. Один и тот же бэкенд обслуживает и кнопки в интерфейсе, и REST-вызовы из ваших скриптов - ничего не теряется в трансляции, никаких облачных посредников, никаких лимитов на запросы. Подключайте Puppeteer или Playwright через wsEndpoint, оркестрируйте задачи через task-groups, шифруйте чувствительное в encrypted-переменных, подписывайте свой JS-код - и получаете полноценную инфраструктуру для мультиаккаунтинга на любом масштабе.

Если ваш текущий браузер (Octo, Multilogin, Dolphin) ограничивает вас облачными квотами и 1000 запросами в день - переход на Afina с локальным API даёт сразу два порядка масштаба и убирает зависимость от чужих серверов.

Установите Afina Browser бесплатно, получите API-ключ в настройках за 30 секунд и попробуйте первый запрос - начните с /api/health, дальше уже само пойдёт. Через час у вас будет автоматизация, на которую в UI вы тратили дни.

FAQ — Часто задаваемые вопросы

Безопасно ли держать API открытым? Можно ли украсть данные через API?

API биндится только на 127.0.0.1 - снаружи доступа нет, локальный фаервол не нужен. Внутри машины - любой процесс, знающий ключ, может вызывать API. Если на машине есть недоверенные процессы (вы запускаете чужой код) - это в принципе не та машина, на которой стоит держать антидетект. Encrypted-переменные не отдаются даже с правильным ключом.

Учитываются ли локальные API-запросы в каком-нибудь лимите?

В текущей версии порт 50778 зашит в feature_flags.rs. Можно поменять перед компиляцией. В runtime - пока нет, но если 50778 занят, сервер автоматически пробует 50779-50787.

Как узнать, что профиль действительно запущен и готов к CDP?

Ответ /api/profiles/start приходит уже после того, как браузер запустился и открыл CDP-эндпоинт. Если получили wsEndpoint - можно сразу подключаться. Если получили ошибку - браузер не стартовал, читайте error в ответе.

Что будет, если API запросов очень много одновременно?

Лимит - 128 одновременных соединений. Сверху - ждут в очереди. Если нужно больше - батчите запросы (большинство эндпоинтов поддерживают bulk-операции: tasks/create принимает массив, proxies/check тоже, и т.д.).

Можно ли API вызывать с другой машины в локальной сети?

Напрямую нет (только 127.0.0.1). Но можно прокинуть через SSH-tunnel или поставить локальный nginx/Caddy в reverse-proxy - на свой страх и риск. Лучший вариант - держать всё на одной машине либо использовать командный доступ Afina с разделением ролей.

Поддерживается ли Webhook - чтобы API сам присылал события?

В текущей версии - через polling (/api/tasks/active, /api/tasks/list?status=error). Webhook-и в roadmap.

А если хочу не возиться с raw HTTP, а взять готовую библиотеку?

Под Node есть пакет afina-mcp - он, помимо MCP-серверной части, экспортирует typed-клиент к REST API. Можно использовать его как обычную библиотеку без MCP-моста. Под Python готового SDK пока нет, но обвязка над requests пишется за час.

Сколько живёт wsEndpoint?

Пока запущен браузер. После /api/profiles/stop или ручного закрытия браузером - endpoint становится недействительным. Если процесс упал и браузер перезапустился, новый wsEndpoint надо получить через повторный start (он отдаст alreadyRunning: true и текущий wsEndpoint без рестарта).

Будет ли это работать на macOS, Windows, Linux одинаково?

Да. API Afina - это HTTP-сервер внутри десктоп-приложения, и оно собирается под все три платформы из одного Rust-кода. Различий в API между платформами нет.

Похожие термины

Читать дальше:Сценарная автоматизация — скрипты | Afina Browser
Никита Корниенко

Привет! Я Mykyta Korniienko — разработчик и основатель Afina Browser. Мне нравится разбираться в сложных вещах и делать из них работающие, понятные решения. Я создаю реалистичные браузерные профили, занимаюсь сетевой аутентичностью (UDP / QUIC / HTTP-3), автоматизацией и масштабируемой SaaS-инфраструктурой.

За годы работы я успел побывать и в backend, и во frontend, и глубоко внутри Chromium-форков — поэтому хорошо понимаю, как всё должно работать в реальных условиях, а не «на бумаге». В своих проектах я всегда делаю упор на безопасность, производительность и честное прохождение антифрод-проверок.

Когда я не за кодом, я, скорее всего, тестирую новые идеи, улучшаю Afina или думаю, как сделать инструменты для automation, privacy и multi-account работы ещё удобнее для профессионалов .

Поделиться