Skip to content
NextCore Docs NextCore Browser Tiếng Việt homestaynextcore.org
On this page

NextCore Browser Local API

Control profiles with scripts running on the same machine: create, open, get the CDP port, arrange windows, back up and restore.

Updated 02/11/20268 min read

What the Local API is

The Local API is a "control port" that NextCore Browser opens right on your machine. Instead of clicking in the app, a program (script) sends commands to this port to create profiles, open browsers, arrange windows… and the app does exactly what it would if you clicked.

What it is for

Task Instead of Call
Create 50 profiles from a list of proxies clicking "Bulk create" and pasting by hand POST /profiles in a loop over a CSV file
Every morning, open the whole "Farm máy 1" group and arrange it on screen 2 opening each profile and dragging each window GET /profiles?group= → POST /start → POST /arrange
Automate pages (sign in, fill forms, read figures) in each profile working by hand in each window POST /start returns wsEndpoint → connect Playwright / Puppeteer
Back up every profile each night Back up… on each profile POST /profiles/:id/backup on a schedule (Task Scheduler / cron)
Connect to self-hosted n8n, Make, Zapier — an HTTP Request node calling 127.0.0.1 (n8n running on the same machine)
Let an AI agent (Claude, Cursor…) manage profiles in plain language — MCP, which runs on the Local API itself
Send groups found by GROUP CRAWL to your CRM / database exporting CSV and importing by hand Push GROUP CRAWL data: the app POSTs to your API or writes to MySQL / PostgreSQL

Turning it on and getting the token

SETTINGS › AI agent (MCP), open Advanced at the bottom of the block: turn on Enable Local API, set the Port (default 19880), and click Show token to see the Token. The bottom right corner of the app footer shows API : while listening, and API off or API error when not.

SETTINGS › AI agent (MCP): MCP turned on, connections for Claude Code · Antigravity · Cursor · VS Code, and Advanced with the port and token
SETTINGS › AI agent (MCP): MCP turned on, connections for Claude Code · Antigravity · Cursor · VS Code, and Advanced with the port and token

bash
curl -H "Authorization: Bearer $NCB_TOKEN" http://127.0.0.1:19880/api/v1/status

MCP on the Local API: tool categories

Since 0.3.172, every MCP tool has a category (_meta.category). New installs only list the core groups (profiles, common page actions, E2E, Kernel), about 49 tools instead of 213, so agents use less context per session. Machines installed earlier keep every category as before.

Repo attribution (setting repoAttribution, off by default): when on, NextCore E2E results include a line for the agent to write to .ncb/e2e/dau-an.md in your repo, and the commit trailer Verified-by: NextCore E2E (N trang, kiểm lại xanh) only when the run found no errors. When off, nothing is written to the repo.

Endpoints

This port also serves MCP at /mcp for AI assistants; since 0.3.166 /mcp?lang=en returns English tool names and errors with NCB-xxxx codes, see MCP.

Method Path Request body Returns
GET /api/v1/status app version, engine; since 0.3.169 also lastAbnormalExit (the last time the app closed abnormally + the NC-CRASH-… code)
GET /api/v1/profiles?group=&q= list of profiles (without proxy passwords)
POST /api/v1/profiles { name?, group?, proxy?, tags?, note?, startUrl?, extensionIds? } the new profile (empty name ⇒ NEXTCORE BROWSER NN). Since 0.3.19 engineId is ignored (always saved as null); every profile runs NextCore Chromium
GET /api/v1/profiles/:id one profile
PATCH /api/v1/profiles/:id the fields to change the profile
DELETE /api/v1/profiles/:id moves it to the trash
POST /api/v1/profiles/:id/start { scale? }: page zoom 0.25–5, default 1 (100%) { pid, debugPort, wsEndpoint }
POST /api/v1/profiles/:id/stop
GET /api/v1/running the profiles currently open
POST /api/v1/arrange { ids?, rows?, cols?, gap?, displayId?, scale? }: scale is saved as the zoom level for Arrange windows; it does not apply to /start (since 0.3.20) { arranged, failed }
GET /api/v1/engines NextCore Chromium on the machine (since 0.3.19 only builds the app downloads; empty engines = not downloaded yet, opening a profile downloads it automatically)
GET/POST /api/v1/extensions POST: { path, isDefault? } extension library
POST /api/v1/profiles/:id/proxy-check exit IP, country, carrier and latency of the assigned proxy
POST /api/v1/profiles/:id/ro-ri checks the profile for leaks: the IP pages see compared with the proxy, WebRTC, IPv6, DNS, time zone, language, QUIC; each item comes with how to fix it
POST /api/v1/profiles/:id/van-tay/sinh-lai regenerates the profile's browser fingerprint
POST /api/v1/profiles/:id/page/{goto|snapshot|click|type|screenshot} { url } · { maxKb } · { ref } · { ref, text, clear?, submit? } · { quality } page actions in an open profile (legacy; new scripts should connect Playwright through wsEndpoint)
GET /api/v1/profiles/:id/emails?limit= the latest messages for the email recorded in the profile's note (NEXTCORE EMAIL)
POST /api/v1/profiles/:id/otp { email?, matKhau? } (saves the email to the profile if sent) { email, otpMoiNhat, soThu, kiemLuc }
POST /api/v1/email/check { email, matKhau, chiDinhHuong? } checks any mailbox; chiDinhHuong: true only discovers the mail server
GET/POST /api/v1/proxies?nguong= POST: { text, kiem?, nhom? } (one proxy per line) the proxy vault (without passwords or IP-rotation links) + shared-IP warnings
GET/PATCH/DELETE /api/v1/proxies/:id PATCH: { nhan?, ghiChu?, nhom?, proxy?, giaMoiGb?, giaThang? } · DELETE: ?goKhoiProfile=1 one proxy in the vault
POST /api/v1/proxies/:id/check · /rotate checks / rotates the proxy's IP
POST /api/v1/proxies/assign · /distribute { proxyId, profileIds } · { proxyIds, profileIds } assigns one proxy to many profiles / spreads many proxies evenly
GET/POST/PATCH/DELETE /api/v1/media-creator/… NEXTCORE MEDIA: account pool, projects, characters, locations, scenes, image/video generation. GET /api/v1/media-creator returns the full state
POST /api/v1/profiles/:id/backup { password (≥ 8 characters), dest? } path to the .ncbak file
POST /api/v1/backups/restore { file, password, onConflict?: 'skip'|'replace'|'keepBoth' } restore result (default skip)

proxy accepts exactly the same formats as the interface. rows and cols must be given together; omit both ⇒ automatic grid. Profiles running Firefox return null for debugPort/wsEndpoint and cannot be arranged.

Code When
401 missing / wrong token
403 the request has an Origin header
404 no such profile
409 the profile is opening / closing; the proxy is assigned to a profile when deleting; the mailbox cannot be read
423 the app is waiting for sign-in: the port is listening but not returning data yet. Once you sign in to NextCore Browser, calls work again

Controlling a profile with Playwright

js
import { chromium } from 'playwright'

const API = 'http://127.0.0.1:19880/api/v1'
const H = { Authorization: `Bearer ${process.env.NCB_TOKEN}`, 'Content-Type': 'application/json' }

const p = await (await fetch(`${API}/profiles`, { method: 'POST', headers: H, body: JSON.stringify({ group: 'Farm máy 1' }) })).json()
const run = await (await fetch(`${API}/profiles/${p.id}/start`, { method: 'POST', headers: H })).json()

const browser = await chromium.connectOverCDP(run.wsEndpoint)
const page = browser.contexts()[0].pages()[0] ?? (await browser.contexts()[0].newPage())
await page.goto('https://homestaynextcore.org')
console.log(await page.title())

await browser.close() // disconnects CDP, the profile stays open
await fetch(`${API}/profiles/${p.id}/stop`, { method: 'POST', headers: H })

Puppeteer: puppeteer.connect({ browserWSEndpoint: run.wsEndpoint }).

Note Scripts can only control profiles while the app is running and signed in. Keep the token like a password: anyone who has the token and can run code on your machine can control every profile.

Sample recipes

Python: create profiles from a proxies.txt file (one proxy per line), then open the first 5 and arrange them in a grid:

python
import os, requests

API = "http://127.0.0.1:19880/api/v1"
H = {"Authorization": f"Bearer {os.environ['NCB_TOKEN']}"}

ids = []
for i, line in enumerate(open("proxies.txt", encoding="utf-8").read().split()):
    p = requests.post(f"{API}/profiles", headers=H, json={"name": f"Shop {i+1:02}", "group": "Farm máy 1", "proxy": line}).json()
    ids.append(p["id"])

for pid in ids[:5]:
    run = requests.post(f"{API}/profiles/{pid}/start", headers=H).json()
    print(pid, run["wsEndpoint"])

requests.post(f"{API}/arrange", headers=H, json={"ids": ids[:5]})

PowerShell: close every open profile (for the end of the day):

powershell
$H = @{ Authorization = "Bearer $env:NCB_TOKEN" }
$api = "http://127.0.0.1:19880/api/v1"
Invoke-RestMethod "$api/running" -Headers $H | ForEach-Object {
  Invoke-RestMethod "$api/profiles/$($_.profileId)/stop" -Method Post -Headers $H
}

Node: back up a whole group to D:\sao-luu (schedule it to run every night):

js
const API = 'http://127.0.0.1:19880/api/v1'
const H = { Authorization: `Bearer ${process.env.NCB_TOKEN}`, 'Content-Type': 'application/json' }
const list = await (await fetch(`${API}/profiles?group=Farm%20m%C3%A1y%201`, { headers: H })).json()
for (const p of list) {
  const r = await fetch(`${API}/profiles/${p.id}/backup`, { method: 'POST', headers: H, body: JSON.stringify({ password: process.env.NCB_BACKUP_PASS, dest: 'D:\\sao-luu' }) })
  console.log(p.name, (await r.json()).file ?? 'lỗi')
}
Was this article helpful?