Push GROUP CRAWL data to your system
NextCore Browser sends the groups it finds to your API or your MySQL / PostgreSQL database: payload, table schema and a sample receiving server.
What this is
GROUP CRAWL saves the Facebook groups it finds to a store on your machine. The app can also push those groups to your own system (a custom CRM, n8n, a table in your company database) after each search run.
Open it at NEXTCORE GROUPCRAWL › the Background jobs line (click to open) › Push data › Settings. There are two destinations, each turned on separately, OFF by default:
| Destination | What the app does |
|---|---|
| API | POSTs JSON in batches (up to 100 groups) to the URL you provide, with an authentication header if set |
| Database MySQL / MariaDB or PostgreSQL | Connects directly to the database, creates the table if it does not exist, and overwrites by group_id (UPSERT) |
- Only the public part of a group is sent: ID, name, link, member count, posts per day, privacy, area, category, and when it was seen. Facebook accounts, profile names, search keywords, posts and member lists are not sent.
- Only changes are sent: the first push sends the whole store; after that, only new groups or groups whose name, figures or classification changed. Changing the URL or the database / table makes the app treat the new destination as empty and send the whole store again.
- When it sends: as soon as a search run ends (including runs stopped midway, since the groups already recorded are real data), right after you turn the switch on, and when you click Push now. A background run checks every minute and sends any groups still waiting.
- A failed push does not break the search run: the store on the machine stays complete. The Push data line in Background jobs shows the result of the latest push (time, number of groups, error message). After a failure, the app retries 10 minutes later, or as soon as the next search run finishes / you click Push now.
- Secrets are encrypted: the authentication header value and the database password are stored with the operating system's encryption (Windows DPAPI, the Linux keyring when available), and the app never shows them again; leaving the field empty keeps the old value. On macOS they are currently stored in plain form in the app's data folder, like proxy passwords and API keys.
(a) Push to an API
The request the app sends
POST https://crm.cua-ban.vn/api/nextcore/groups
Content-Type: application/json; charset=utf-8
User-Agent: NextCoreBrowser/<app version> (+group-crawl)
Authorization: Bearer <value you enter> ← header name can be changed (X-Api-Key…), empty ⇒ not sent{
"nguon": "nextcore-browser",
"phienBan": 1,
"guiLuc": "2026-10-19T01:36:12.418Z",
"kiem": false,
"soGroup": 2,
"groups": [
{
"id": "1481410332813761",
"ten": "Homestay Đà Lạt Giá Rẻ View Đẹp",
"url": "https://www.facebook.com/groups/homestaydalatgiare/",
"rutGon": "homestaydalatgiare",
"thanhVien": 48307,
"thanhVienLamTron": false,
"baiNgay": 90,
"cheDo": "PUBLIC",
"khuVucId": 38,
"khuVuc": "Lâm Đồng",
"danhMucId": 7,
"danhMuc": "Homestay & khách sạn",
"lanDau": "2026-10-17T06:00:00.000Z",
"lanCuoi": "2026-10-19T01:12:00.000Z"
}
]
}| Field | Type | Meaning |
|---|---|---|
phienBan |
number | payload version, currently 1; a structure change will increase it |
kiem |
bool | true when you click Test connection (an empty batch, groups: []); a 2xx response passes, do not write anything |
groups[].id |
string | the Facebook group ID (numeric; for groups whose numeric ID could not be read, the short name), the key for overwriting |
rutGon |
string | null | the name part of the facebook.com/ link, null if the link uses the numeric ID |
thanhVien |
number | null | member count; thanhVienLamTron: true means Facebook rounded the number (27K ⇒ 27000) |
baiNgay |
number | null | posts per day as Facebook shows on the search page |
cheDo |
PUBLIC | PRIVATE | null |
group privacy |
khuVucId / khuVuc |
number / string | null | current province in the NextCore catalog |
danhMucId / danhMuc |
number / string | null | NextCore industry category |
lanDau / lanCuoi |
ISO 8601 UTC | first / most recent time the app saw the group |
What the receiving server must return
- 2xx ⇒ the app treats the batch as received and marks it sent. The response body is not read.
- 429 or 5xx, a network failure, or more than 15 seconds ⇒ the app retries within the same run: waits 1 second, then 4 seconds (3 attempts in total). Still failing ⇒ it logs the error and retries 10 minutes later.
- Other 4xx (401, 403, 404, 413…) ⇒ stops immediately, no retry (fix the configuration, then click Push now).
- Redirects (3xx) are not followed, so provide the final URL.
- The same group can arrive several times (each time its figures change) ⇒ overwrite by
id, do not insert duplicates.
Sample receiving server (Node.js, no libraries)
// node nhan-groups.mjs — listens on :8080, checks the key, overwrites by id into groups.json
import http from 'node:http'
import fs from 'node:fs'
const KHOA = process.env.KHOA_NHAN // same as the header value set in the app (Authorization: Bearer …)
const kho = fs.existsSync('groups.json') ? JSON.parse(fs.readFileSync('groups.json', 'utf8')) : {}
http.createServer((req, res) => {
if (req.method !== 'POST' || req.url !== '/api/nextcore/groups') return res.writeHead(404).end()
if (req.headers.authorization !== `Bearer ${KHOA}`) return res.writeHead(401).end()
let chu = ''
req.on('data', (c) => (chu += c)).on('end', () => {
const lo = JSON.parse(chu)
if (!lo.kiem) for (const g of lo.groups) kho[g.id] = g
fs.writeFileSync('groups.json', JSON.stringify(kho, null, 2))
res.writeHead(200, { 'Content-Type': 'application/json' }).end(JSON.stringify({ ok: true, nhan: lo.groups.length }))
})
}).listen(8080)n8n: a Webhook node (POST, Response 200) → Split Out on the groups field → write to a Google Sheet / database keyed by id.
(b) Push directly into a MySQL / PostgreSQL database
Fill in the Type (MySQL / MariaDB or PostgreSQL), Host, Port (3306 / 5432), Database name, User, Password, Table (default nextcore_groups), and optionally SSL (turn it on when the database is outside your local network; the app verifies the certificate). Click Test connection before turning it on:
- Đã kết nối · bảng … chưa có (Connected · table … does not exist yet) ⇒ on the first push the app runs
CREATE TABLE IF NOT EXISTSwith the schema below. - Đã kết nối · bảng … khớp lược đồ (Connected · table … matches the schema) ⇒ ready to use.
- Bảng … đã có nhưng thiếu cột … (Table … exists but is missing column …) ⇒ the app does not alter your table: add the missing columns, or choose a different table name so the app creates it. Extra columns of your own in the table are fine.
Minimum privileges for the database user: SELECT, INSERT, UPDATE on the table (plus CREATE if you let the app create the table). Create a dedicated user for NextCore Browser; do not use root.
Table schema
MySQL / MariaDB:
CREATE TABLE IF NOT EXISTS `nextcore_groups` (
`group_id` VARCHAR(64) NOT NULL,
`ten` VARCHAR(255) NOT NULL,
`url` VARCHAR(512) NOT NULL,
`rut_gon` VARCHAR(128) NULL,
`thanh_vien` BIGINT NULL,
`thanh_vien_lam_tron` BOOLEAN NOT NULL DEFAULT FALSE,
`bai_ngay` DOUBLE NULL,
`che_do` VARCHAR(16) NULL,
`khu_vuc_id` INT NULL,
`khu_vuc` VARCHAR(128) NULL,
`danh_muc_id` INT NULL,
`danh_muc` VARCHAR(160) NULL,
`lan_dau` DATETIME(3) NOT NULL,
`lan_cuoi` DATETIME(3) NOT NULL,
`day_luc` DATETIME(3) NOT NULL,
PRIMARY KEY (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;PostgreSQL:
CREATE TABLE IF NOT EXISTS "nextcore_groups" (
"group_id" VARCHAR(64) NOT NULL,
"ten" VARCHAR(255) NOT NULL,
"url" VARCHAR(512) NOT NULL,
"rut_gon" VARCHAR(128) NULL,
"thanh_vien" BIGINT NULL,
"thanh_vien_lam_tron" BOOLEAN NOT NULL DEFAULT FALSE,
"bai_ngay" DOUBLE PRECISION NULL,
"che_do" VARCHAR(16) NULL,
"khu_vuc_id" INTEGER NULL,
"khu_vuc" VARCHAR(128) NULL,
"danh_muc_id" INTEGER NULL,
"danh_muc" VARCHAR(160) NULL,
"lan_dau" TIMESTAMPTZ NOT NULL,
"lan_cuoi" TIMESTAMPTZ NOT NULL,
"day_luc" TIMESTAMPTZ NOT NULL,
PRIMARY KEY ("group_id")
);- Columns mean the same as the API payload fields (
thanh_vien_lam_tron=thanhVienLamTron…);day_luc= when the app last wrote the row. - Times are stored in UTC (MySQL
DATETIME(3)stores UTC time; PostgreSQLTIMESTAMPTZ). - Overwrite by
group_id:INSERT … ON DUPLICATE KEY UPDATE(MySQL) /INSERT … ON CONFLICT ("group_id") DO UPDATE(PostgreSQL).lan_daukeeps the value from the first write; every other column is updated.
Reading it back: example
-- 20 largest Lâm Đồng groups, updated in the last 7 days
SELECT ten, url, thanh_vien, bai_ngay
FROM nextcore_groups
WHERE khu_vuc = 'Lâm Đồng' AND lan_cuoi >= NOW() - INTERVAL 7 DAY
ORDER BY thanh_vien DESC
LIMIT 20;Quick answers
What happens when a group is deleted from the store? The app does not send delete commands; the destination keeps the last version it received. Groups deleted and blocked in the app are not found again, so they are no longer sent.
Can two machines push to the same table? Yes. The key is group_id, and the machine that sends later overwrites with the newer figures.
Is there a rate limit? Each run sends at most 20 batches × 100 groups; larger stores continue in the background run every minute.
Language
Since 0.3.172, the screen for pushing GROUP CRAWL data to your system shows English when you choose English in Cài đặt › Giao diện (Settings › Appearance), or choose Use system setting on a machine set to English. Content you enter and data taken from Facebook stay in their original language.