Action Log API: как клиенты выносят события профилей в свои системы


Alex Phillips
Customer Service Specialist
Стандартный интерфейс Octo Browser показывает, что происходит с вашим профилем прямо сейчас. Но если сотнями или тысячами профилей управляет команда — в какой-то момент нужно автоматически передавать события о профилях в CRM, систему контроля доступа или внутренний дашборд.
Для этого Octo предоставляет Action Log — WebSocket-эндпойнт, который передает события в реальном времени. Мы добавили его для команд, у которых работа с Octo встроена в собственную CRM, ERP или систему учета. На данный момент в Action Log Octo десять типов событий — от старта и остановки профиля до передачи, удаления и изменения прокси, — и список пополняется по мере того, как команды находят новые сценарии.
Ниже — два примера того, как вы можете применять Action Log на практике: контроль доступа в реальном времени и управленческий учет на масштабе.
Содержание
Управляйте любым количеством аккаунтов без банов, рутины и лишних расходов.
Хотите попробовать Octo Browser со скидкой?
По промокоду OCTOBLOG получите 30% скидку на любую подписку. Предложение действительно только для новых пользователей.
Права доступа без ручной сверки
У одного из клиентов с профилями Octo Browser работают сотрудники из разных отделов. У каждого свой уровень доступа через собственное расширение, используемое поверх Octo. Прежде чем выдать нужные права, система должна понять, кто сейчас работает с конкретным профилем.
Без Action Log не было видно, кто именно запускает профиль. Систему уровней доступа приходилось строить по косвенным признакам: можно было увидеть, что профиль используется, но нельзя было понять, кем именно.
Процесс изменился, когда мы добавили в Action Log событие profiles.started: user_email приходит в момент запуска, и права применяются автоматически. Эта связка события → права стала основой большинства внутренних автоматизаций наших клиентов.
Это постоянно работающий механизм, который реагирует на каждый запуск профиля в реальном времени. События обрабатываются на лету и сохраняются в собственной базе.
На интеграцию клиенту потребовался один разработчик и около часа — Action Log встроили в уже существующую систему прав как дополнительный модуль, а не создавали процесс заново.
Учет команды за секунды вместо часов
Другой клиент готовит большой объем аккаунтов силами распределенной команды: много людей и много профилей одновременно. При таком масштабе быстро теряется общая картина: кто сколько профилей ведет, сколько готово, сколько выдано, сколько удалено, кем и почему.
До перехода на собственную систему учет шел в таблицах. Любой срез по команде требовал ручного прохода по тегам и записям: сбор актуальных данных занимал от пары часов до суток, а к моменту готовности результат уже частично устаревал.
Когда мы расширили функционал Action Log, клиент написал собственную CRM, которая через API получает события из профилей и складывает их в единую картину: сколько профилей в работе у каждого сотрудника, сколько готовых, сколько выдано, сколько удалено — с привязкой к тому, кто и когда выполнил действие.
Все данные отображаются на дашборде в виде счетчиков и статусов и обновляются автоматически. Отчет, на подготовку которого раньше уходили часы, теперь делается за 30 секунд — достаточно открыть нужный раздел.
Систему разработали без привлечения штатного разработчика, с помощью AI-инструментов для написания кода. На создание рабочей версии CRM с интеграцией по API ушла неделя.
Как еще можно использовать Action Log
Один и тот же API закрывает разные задачи: операционный контроль в реальном времени, учет действий и автоматизацию внутренних процессов. В обоих рассмотренных случаях интеграция заняла часы или дни, а не месяцы, и не потребовала отдельной команды разработки.
Принцип во всех сценариях одинаков: Octo передает события о действиях с профилями в реальном времени, а клиентская система сама решает, как их использовать и хранить.
Именно реальные потребности клиентов во многом определяют развитие Action Log. События profiles.transferred, profiles.deleted, profiles.proxy_changed и другие появились по запросам команд, которые уже строили процессы вокруг API, но сталкивались с нехваткой данных. В дальнейшем набор событий будет расширяться в том же направлении.
Помимо описанных выше кейсов, Action Log можно использовать и для других задач:
Биллинг и внутренние расчеты:
run_durationизprofiles.stoppedдает точную длительность сессии — удобно, если вы тарифицируете работу сотрудников по фактическому времени с профилем, без отдельного тайм-трекера.Аудит удалений:
profiles.deletedиprofiles.trashedс привязкой кuser_emailпозволяют быстро находить, кто и когда удалил конкретный профиль, без необходимости спрашивать команду вручную.Контроль передачи профилей:
profiles.transferredсодержит обе стороны в одной записи — отправителя и получателя, без сопоставления данных из разных источников.Уведомления о потере данных:
profiles.force_stoppedозначает, что запущенный профиль перевели в статус неактивного, потому что он не был закрыт штатно. Результаты работы в профиле на момент принудительной остановки не синхронизируются — стоит предупреждать коллег, которые с ним работали: их изменения не сохранятся. Подробнее в документации.Учет смены прокси: тройка
proxy_assigned/proxy_unassigned/proxy_changedподходит для сценариев, где внешним системам важно знать текущий прокси профиля без периодического опроса.
При этом есть важное ограничение: Action Log работает в потоковом режиме и хранит данные только за последние 24 часа. Поэтому если события нужны для аудита или долгосрочной аналитики, их необходимо сохранять в собственной системе по мере поступления.
Теперь разберем доступные события и покажем, как с ними работать.
Как работает Action Log в Octo Browser
Тип: WebSocket
URL:
wss://app.octobrowser.net/api/v2/automation/ws/action_logАвторизация: токен в заголовке
X-Octo-Api-Token
После подключения сервер сам присылает события по мере их появления — повторные запросы не нужны. Каждое сообщение — StreamPage: массив событий и watermark.
{ "items": [ { "uuid": "550e8400-e29b-41d4-a716-446655440000", "action": "profiles.started", "time": 1707053400, "user_email": "user@example.com", "object_type": "profile", "object_id": "a1b2c3d4e5f67890abcdef1234567890", "object_title": "Octo Browser Profile", "data": { "connection_data": { "ip": "203.0.113.42", "countryCode": "FR", "countryName": "France", "subdivisions": ["Île-de-France", "Paris"], "postalCode": "75008", "cityName": "Paris", "timezone": "Europe/Paris", "lat": 48.8566, "lon": 2.3522, "languages": ["fr", "en-US", "en"], "isp": "Example Networks Ltd", "connectionType": "Cable/DSL" } } } ], "watermark": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "time": 1707053400 } }
{ "items": [ { "uuid": "550e8400-e29b-41d4-a716-446655440000", "action": "profiles.started", "time": 1707053400, "user_email": "user@example.com", "object_type": "profile", "object_id": "a1b2c3d4e5f67890abcdef1234567890", "object_title": "Octo Browser Profile", "data": { "connection_data": { "ip": "203.0.113.42", "countryCode": "FR", "countryName": "France", "subdivisions": ["Île-de-France", "Paris"], "postalCode": "75008", "cityName": "Paris", "timezone": "Europe/Paris", "lat": 48.8566, "lon": 2.3522, "languages": ["fr", "en-US", "en"], "isp": "Example Networks Ltd", "connectionType": "Cable/DSL" } } } ], "watermark": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "time": 1707053400 } }
Сейчас Action Log поддерживает десять типов событий:
profiles.started— профиль запущен;profiles.stopped— профиль остановлен;profiles.force_stopped— профиль принудительно завершен;profiles.transferred— профиль передан другому пользователю;profiles.trashed— профиль перемещен в корзину;profiles.deleted— профиль удален;profiles.updated— профиль изменен;profiles.proxy_assigned— прокси назначен профилю;profiles.proxy_unassigned— прокси снят с профиля;profiles.proxy_changed— прокси изменен на другой.
Для устойчивости к разрывам связи в каждом сообщении есть watermark — UUID и время последнего события. При переподключении достаточно передать этот UUID в параметре after_uuid: стрим отправит все, что произошло за время простоя, не теряя и не дублируя события. Второй способ — стартовать с конкретного момента через from_timestamp. Ограничение одно: события хранятся 24 часа, это живой поток, а не архив.
Это работает и при массовых операциях: если сотрудник перемещает в корзину сразу сто профилей, в потоке появятся все сто событий, каждое со своим object_id — ни одно не потеряется и не задвоится.
Подробнее о работе Action Log можно прочитать в документации.
Что лежит в data — разбор по событиям
Набор полей внутри data зависит от action. Вот что приходит для каждого из десяти типов:
Событие | Что в |
|
|
|
|
|
|
|
|
|
|
|
|
| те же поля с префиксами |
profiles.stopped
Длительность сессии приходит в формате ISO 8601, а не как число секунд:
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
profiles.updated
changeset — не фиксированный список полей, а динамический дифф: в нем только то, что поменялось в этот раз. Например, при изменении нескольких настроек профиля сразу приходит вот что:
{ "action": "profiles.updated", "data": { "changeset": { "description": { "old_value": "", "new_value": "Test action log" }, "start_pages": { "added": ["http://google.com", "http://facebook.com"], "removed": [] }, "storage_options": { "added": ["serviceworkers", "localstorage"], "removed": [] }, "bookmarks": { "added": ["https://ebay.com", "https://amazon.com"], "removed": [] }, "launch_args": { "added": ["--start-maximized"], "removed": [] }, "images_load_limit": { "old_value": null, "new_value": 10240 }, "local_cache": { "old_value": false, "new_value": true }, "fingerprint": {} } } }
{ "action": "profiles.updated", "data": { "changeset": { "description": { "old_value": "", "new_value": "Test action log" }, "start_pages": { "added": ["http://google.com", "http://facebook.com"], "removed": [] }, "storage_options": { "added": ["serviceworkers", "localstorage"], "removed": [] }, "bookmarks": { "added": ["https://ebay.com", "https://amazon.com"], "removed": [] }, "launch_args": { "added": ["--start-maximized"], "removed": [] }, "images_load_limit": { "old_value": null, "new_value": 10240 }, "local_cache": { "old_value": false, "new_value": true }, "fingerprint": {} } } }
Видны два паттерна:
для одиночных значений (
description,images_load_limit,local_cache) приходит параold_value/new_value;для списков (
start_pages,storage_options,bookmarks,launch_args) —added/removed.
fingerprint — исключение: ключ появляется, когда отпечаток действительно менялся, но всегда как пустой объект, без деталей, что конкретно поменялось внутри. Общее правило простое: если поле не менялось, его ключа в changeset не будет.
profiles.deleted
{ "action": "profiles.deleted", "data": { "manual": true } }
{ "action": "profiles.deleted", "data": { "manual": true } }
profiles.proxy_changed
Сравнивает старый и новый прокси одним событием:
{ "action": "profiles.proxy_changed", "data": { "old_proxy_uuid": "370b0ce963194f68803a812dd42db4be", "old_proxy_title": "Netlabs GB England", "old_url": "socks5://user:pass@proxy.example.com:1080", "new_proxy_uuid": "9c51385c3e2b417d9b34fc305a49d4f6", "new_proxy_title": "Netlabs GB England Towcester", "new_url": "socks5://user:pass@proxy2.example.com:1080" } }
{ "action": "profiles.proxy_changed", "data": { "old_proxy_uuid": "370b0ce963194f68803a812dd42db4be", "old_proxy_title": "Netlabs GB England", "old_url": "socks5://user:pass@proxy.example.com:1080", "new_proxy_uuid": "9c51385c3e2b417d9b34fc305a49d4f6", "new_proxy_title": "Netlabs GB England Towcester", "new_url": "socks5://user:pass@proxy2.example.com:1080" } }
profiles.proxy_assigned и profiles.proxy_unassigned отдают те же поля, но без префиксов old_/new_ — по одному набору на событие, а не сравнение.
Отдельно поле temporary: true означает, что прокси вставлен через быстрое действие (например, вставкой строки), а не назначен обычным способом через настройки профиля.
profiles.trashed и автоудаление
profiles.trashed приходит с пустым data — как и force_stopped. Если профиль не восстановить и не удалить вручную, он удалится сам через 72 часа — подробнее в документации о корзине.
profiles.transferred
Одно событие содержит обе стороны сразу:
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
user_email — как и в любом другом событии, тот, кто выполнил действие, то есть отправитель трансфера.
data.receiver — получатель.
Подключение и переподключение
Подключиться можно любым клиентом с поддержкой WebSocket.
На Node.js это выглядит так:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
Что означает каждое поле в пришедшем событии:
uuid — идентификатор самого события, а не профиля; уникален для каждой записи, даже если несколько событий произошли в одну секунду;
action — тип действия из списка выше;
time — время события в Unix-формате;
user_email — почта пользователя, который совершил действие;
object_type — тип объекта, к которому относится событие;
object_id — идентификатор самого профиля, отдельный от UUID события;
object_title — название профиля на момент события;
data — детали, зависящие от
action, разбор выше.
Если профиль остановить, придет второе событие — profiles.stopped, с новым uuid, но тем же object_id, потому что профиль тот же. По object_id можно связывать все события одного профиля в единую историю на своей стороне — object_id не меняется на всем протяжении жизни профиля, от старта до удаления.
Чтобы продолжить стрим после разрыва связи, достаточно сохранить uuid из последнего полученного watermark и передать его в after_uuid:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?after_uuid=UUID', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?after_uuid=UUID', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
Соединение сразу отправит события, случившиеся после этого UUID, а затем продолжит работать как обычный стрим — повторный after_uuid нужен только при следующем разрыве.
Если сохраненного watermark нет — например, после долгого простоя вы знаете только примерное время отключения — можно стартовать по времени через from_timestamp (Unix-время в секундах):
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?from_timestamp=TIMESTAMP', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?from_timestamp=TIMESTAMP', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
Если вы только начинаете работать с автоматизацией, то подробнее про API Octo Browser мы рассказали в отдельной статье.
Заключение
Action Log позволяет использовать события Octo Browser как часть собственной инфраструктуры: передавать их в CRM, систему контроля доступа, аналитику или другие внутренние инструменты. Octo сообщает, что произошло с профилем, а дальше вы сами определяете, как обработать, сохранить и использовать эти данные.
Если для вашего сценария не хватает конкретного события в Action Log — расскажите нам о нем. Многие из доступных сегодня событий появились именно из реальных задач команд, работающих с API.
Управляйте любым количеством аккаунтов без банов, рутины и лишних расходов.
Хотите попробовать Octo Browser со скидкой?
По промокоду OCTOBLOG получите 30% скидку на любую подписку. Предложение действительно только для новых пользователей.
Права доступа без ручной сверки
У одного из клиентов с профилями Octo Browser работают сотрудники из разных отделов. У каждого свой уровень доступа через собственное расширение, используемое поверх Octo. Прежде чем выдать нужные права, система должна понять, кто сейчас работает с конкретным профилем.
Без Action Log не было видно, кто именно запускает профиль. Систему уровней доступа приходилось строить по косвенным признакам: можно было увидеть, что профиль используется, но нельзя было понять, кем именно.
Процесс изменился, когда мы добавили в Action Log событие profiles.started: user_email приходит в момент запуска, и права применяются автоматически. Эта связка события → права стала основой большинства внутренних автоматизаций наших клиентов.
Это постоянно работающий механизм, который реагирует на каждый запуск профиля в реальном времени. События обрабатываются на лету и сохраняются в собственной базе.
На интеграцию клиенту потребовался один разработчик и около часа — Action Log встроили в уже существующую систему прав как дополнительный модуль, а не создавали процесс заново.
Учет команды за секунды вместо часов
Другой клиент готовит большой объем аккаунтов силами распределенной команды: много людей и много профилей одновременно. При таком масштабе быстро теряется общая картина: кто сколько профилей ведет, сколько готово, сколько выдано, сколько удалено, кем и почему.
До перехода на собственную систему учет шел в таблицах. Любой срез по команде требовал ручного прохода по тегам и записям: сбор актуальных данных занимал от пары часов до суток, а к моменту готовности результат уже частично устаревал.
Когда мы расширили функционал Action Log, клиент написал собственную CRM, которая через API получает события из профилей и складывает их в единую картину: сколько профилей в работе у каждого сотрудника, сколько готовых, сколько выдано, сколько удалено — с привязкой к тому, кто и когда выполнил действие.
Все данные отображаются на дашборде в виде счетчиков и статусов и обновляются автоматически. Отчет, на подготовку которого раньше уходили часы, теперь делается за 30 секунд — достаточно открыть нужный раздел.
Систему разработали без привлечения штатного разработчика, с помощью AI-инструментов для написания кода. На создание рабочей версии CRM с интеграцией по API ушла неделя.
Как еще можно использовать Action Log
Один и тот же API закрывает разные задачи: операционный контроль в реальном времени, учет действий и автоматизацию внутренних процессов. В обоих рассмотренных случаях интеграция заняла часы или дни, а не месяцы, и не потребовала отдельной команды разработки.
Принцип во всех сценариях одинаков: Octo передает события о действиях с профилями в реальном времени, а клиентская система сама решает, как их использовать и хранить.
Именно реальные потребности клиентов во многом определяют развитие Action Log. События profiles.transferred, profiles.deleted, profiles.proxy_changed и другие появились по запросам команд, которые уже строили процессы вокруг API, но сталкивались с нехваткой данных. В дальнейшем набор событий будет расширяться в том же направлении.
Помимо описанных выше кейсов, Action Log можно использовать и для других задач:
Биллинг и внутренние расчеты:
run_durationизprofiles.stoppedдает точную длительность сессии — удобно, если вы тарифицируете работу сотрудников по фактическому времени с профилем, без отдельного тайм-трекера.Аудит удалений:
profiles.deletedиprofiles.trashedс привязкой кuser_emailпозволяют быстро находить, кто и когда удалил конкретный профиль, без необходимости спрашивать команду вручную.Контроль передачи профилей:
profiles.transferredсодержит обе стороны в одной записи — отправителя и получателя, без сопоставления данных из разных источников.Уведомления о потере данных:
profiles.force_stoppedозначает, что запущенный профиль перевели в статус неактивного, потому что он не был закрыт штатно. Результаты работы в профиле на момент принудительной остановки не синхронизируются — стоит предупреждать коллег, которые с ним работали: их изменения не сохранятся. Подробнее в документации.Учет смены прокси: тройка
proxy_assigned/proxy_unassigned/proxy_changedподходит для сценариев, где внешним системам важно знать текущий прокси профиля без периодического опроса.
При этом есть важное ограничение: Action Log работает в потоковом режиме и хранит данные только за последние 24 часа. Поэтому если события нужны для аудита или долгосрочной аналитики, их необходимо сохранять в собственной системе по мере поступления.
Теперь разберем доступные события и покажем, как с ними работать.
Как работает Action Log в Octo Browser
Тип: WebSocket
URL:
wss://app.octobrowser.net/api/v2/automation/ws/action_logАвторизация: токен в заголовке
X-Octo-Api-Token
После подключения сервер сам присылает события по мере их появления — повторные запросы не нужны. Каждое сообщение — StreamPage: массив событий и watermark.
{ "items": [ { "uuid": "550e8400-e29b-41d4-a716-446655440000", "action": "profiles.started", "time": 1707053400, "user_email": "user@example.com", "object_type": "profile", "object_id": "a1b2c3d4e5f67890abcdef1234567890", "object_title": "Octo Browser Profile", "data": { "connection_data": { "ip": "203.0.113.42", "countryCode": "FR", "countryName": "France", "subdivisions": ["Île-de-France", "Paris"], "postalCode": "75008", "cityName": "Paris", "timezone": "Europe/Paris", "lat": 48.8566, "lon": 2.3522, "languages": ["fr", "en-US", "en"], "isp": "Example Networks Ltd", "connectionType": "Cable/DSL" } } } ], "watermark": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "time": 1707053400 } }
Сейчас Action Log поддерживает десять типов событий:
profiles.started— профиль запущен;profiles.stopped— профиль остановлен;profiles.force_stopped— профиль принудительно завершен;profiles.transferred— профиль передан другому пользователю;profiles.trashed— профиль перемещен в корзину;profiles.deleted— профиль удален;profiles.updated— профиль изменен;profiles.proxy_assigned— прокси назначен профилю;profiles.proxy_unassigned— прокси снят с профиля;profiles.proxy_changed— прокси изменен на другой.
Для устойчивости к разрывам связи в каждом сообщении есть watermark — UUID и время последнего события. При переподключении достаточно передать этот UUID в параметре after_uuid: стрим отправит все, что произошло за время простоя, не теряя и не дублируя события. Второй способ — стартовать с конкретного момента через from_timestamp. Ограничение одно: события хранятся 24 часа, это живой поток, а не архив.
Это работает и при массовых операциях: если сотрудник перемещает в корзину сразу сто профилей, в потоке появятся все сто событий, каждое со своим object_id — ни одно не потеряется и не задвоится.
Подробнее о работе Action Log можно прочитать в документации.
Что лежит в data — разбор по событиям
Набор полей внутри data зависит от action. Вот что приходит для каждого из десяти типов:
Событие | Что в |
|
|
|
|
|
|
|
|
|
|
|
|
| те же поля с префиксами |
profiles.stopped
Длительность сессии приходит в формате ISO 8601, а не как число секунд:
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
profiles.updated
changeset — не фиксированный список полей, а динамический дифф: в нем только то, что поменялось в этот раз. Например, при изменении нескольких настроек профиля сразу приходит вот что:
{ "action": "profiles.updated", "data": { "changeset": { "description": { "old_value": "", "new_value": "Test action log" }, "start_pages": { "added": ["http://google.com", "http://facebook.com"], "removed": [] }, "storage_options": { "added": ["serviceworkers", "localstorage"], "removed": [] }, "bookmarks": { "added": ["https://ebay.com", "https://amazon.com"], "removed": [] }, "launch_args": { "added": ["--start-maximized"], "removed": [] }, "images_load_limit": { "old_value": null, "new_value": 10240 }, "local_cache": { "old_value": false, "new_value": true }, "fingerprint": {} } } }
Видны два паттерна:
для одиночных значений (
description,images_load_limit,local_cache) приходит параold_value/new_value;для списков (
start_pages,storage_options,bookmarks,launch_args) —added/removed.
fingerprint — исключение: ключ появляется, когда отпечаток действительно менялся, но всегда как пустой объект, без деталей, что конкретно поменялось внутри. Общее правило простое: если поле не менялось, его ключа в changeset не будет.
profiles.deleted
{ "action": "profiles.deleted", "data": { "manual": true } }
profiles.proxy_changed
Сравнивает старый и новый прокси одним событием:
{ "action": "profiles.proxy_changed", "data": { "old_proxy_uuid": "370b0ce963194f68803a812dd42db4be", "old_proxy_title": "Netlabs GB England", "old_url": "socks5://user:pass@proxy.example.com:1080", "new_proxy_uuid": "9c51385c3e2b417d9b34fc305a49d4f6", "new_proxy_title": "Netlabs GB England Towcester", "new_url": "socks5://user:pass@proxy2.example.com:1080" } }
profiles.proxy_assigned и profiles.proxy_unassigned отдают те же поля, но без префиксов old_/new_ — по одному набору на событие, а не сравнение.
Отдельно поле temporary: true означает, что прокси вставлен через быстрое действие (например, вставкой строки), а не назначен обычным способом через настройки профиля.
profiles.trashed и автоудаление
profiles.trashed приходит с пустым data — как и force_stopped. Если профиль не восстановить и не удалить вручную, он удалится сам через 72 часа — подробнее в документации о корзине.
profiles.transferred
Одно событие содержит обе стороны сразу:
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
user_email — как и в любом другом событии, тот, кто выполнил действие, то есть отправитель трансфера.
data.receiver — получатель.
Подключение и переподключение
Подключиться можно любым клиентом с поддержкой WebSocket.
На Node.js это выглядит так:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
Что означает каждое поле в пришедшем событии:
uuid — идентификатор самого события, а не профиля; уникален для каждой записи, даже если несколько событий произошли в одну секунду;
action — тип действия из списка выше;
time — время события в Unix-формате;
user_email — почта пользователя, который совершил действие;
object_type — тип объекта, к которому относится событие;
object_id — идентификатор самого профиля, отдельный от UUID события;
object_title — название профиля на момент события;
data — детали, зависящие от
action, разбор выше.
Если профиль остановить, придет второе событие — profiles.stopped, с новым uuid, но тем же object_id, потому что профиль тот же. По object_id можно связывать все события одного профиля в единую историю на своей стороне — object_id не меняется на всем протяжении жизни профиля, от старта до удаления.
Чтобы продолжить стрим после разрыва связи, достаточно сохранить uuid из последнего полученного watermark и передать его в after_uuid:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?after_uuid=UUID', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
Соединение сразу отправит события, случившиеся после этого UUID, а затем продолжит работать как обычный стрим — повторный after_uuid нужен только при следующем разрыве.
Если сохраненного watermark нет — например, после долгого простоя вы знаете только примерное время отключения — можно стартовать по времени через from_timestamp (Unix-время в секундах):
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?from_timestamp=TIMESTAMP', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
Если вы только начинаете работать с автоматизацией, то подробнее про API Octo Browser мы рассказали в отдельной статье.
Заключение
Action Log позволяет использовать события Octo Browser как часть собственной инфраструктуры: передавать их в CRM, систему контроля доступа, аналитику или другие внутренние инструменты. Octo сообщает, что произошло с профилем, а дальше вы сами определяете, как обработать, сохранить и использовать эти данные.
Если для вашего сценария не хватает конкретного события в Action Log — расскажите нам о нем. Многие из доступных сегодня событий появились именно из реальных задач команд, работающих с API.
Следите за последними новостями Octo Browser
Нажимая кнопку, вы соглашаетесь с нашей политикой конфиденциальности.
Следите за последними новостями Octo Browser
Нажимая кнопку, вы соглашаетесь с нашей политикой конфиденциальности.
Следите за последними новостями Octo Browser
Нажимая кнопку, вы соглашаетесь с нашей политикой конфиденциальности.

Присоединяйтесь к Octo Browser сейчас
Вы можете обращаться за помощью к нашим специалистам службы поддержки в чате в любое время.

Присоединяйтесь к Octo Browser сейчас
Вы можете обращаться за помощью к нашим специалистам службы поддержки в чате в любое время.
Присоединяйтесь к Octo Browser сейчас
Вы можете обращаться за помощью к нашим специалистам службы поддержки в чате в любое время.
