Afina

Скачати додаток

AppleWindows
UA
БлогБлог

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 не запущена. Для health-перевірки ключ передавати не потрібно.

Крок 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, яка віддає ті самі можливості ШІ-агентам (Claude, ChatGPT, Cursor) через Model Context Protocol. Виникає резонне питання: що використовувати - MCP чи прямий API?

КритерійПрямий REST APIMCP-сервер
Хто користувачРозробник з кодомШІ-агент або людина в чаті
Контроль над логікоюПовнийЧерез промпт
Швидкість розробкиПовільніше (треба писати код)Миттєво (фраза в чаті)
Відтворюваність100% (код детермінований)Залежить від моделі
Підходить для CI/CDТакНі (немає ШІ в пайплайні)
Інтеграція в наявний кодІдеальноНе призначений
Рівень абстракціїEndpoint-рівеньНаміри рівня "зроби X"

Беріть REST API, якщо:

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

Беріть MCP, якщо:

  • Ви в чаті з Claude/ChatGPT і хочете "просто говорити, що потрібно".
  • Прототипуєте ідеї, досліджуєте можливості.
  • Команда без програмістів, але ШІ-агент уже під рукою.

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

Антидетект-браузер без 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-запити в якомусь ліміті?

Ні. 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 або думаю, як зробити інструменти для автоматизації, privacy та multi-account роботи ще зручнішими для професіоналів.

Поділитися