Node.js
Connect with Puppeteer
Social Browser uses the running Chromium debugging surface, so an external Node.js process can attach with puppeteer-core. Set defaultViewport: null so Puppeteer does not impose its normal 800×600 viewport on an existing Social Browser workspace.
const puppeteer = require("puppeteer-core"); const browser = await puppeteer.connect({ browserURL: "http://127.0.0.1:60101", defaultViewport: null, }); const pages = await browser.pages(); for (const page of pages) { console.log(await page.title(), page.url()); } // Disconnect your client without closing Social Browser. await browser.disconnect();Find the page you actually want
const pages = await browser.pages(); const page = pages.find(p => p.url().startsWith("https://example.com/") ); if (!page) { throw new Error("Target page is not currently open"); } console.log({ title: await page.title(), url: page.url(), });For multi-Profile workflows, do not assume the first page returned belongs to the intended Profile. Resolve and verify the target before changing it.
Simple read + action example
await page.waitForSelector("#search", { visible: true }); await page.type("#search", "Social Browser"); await page.click('button[type="submit"]'); await page.waitForSelector(".results", { visible: true }); const titles = await page.$$eval(".result-card h2", nodes => nodes.map(node => node.textContent.trim()) ); console.log(titles);Main Process bridge
Run real Puppeteer against the exact current tab
SOCIALBROWSER.page.runPuppeteer() is intended for trusted User Scripts. The callback runs with real Puppeteer in the Main Process and Social Browser resolves the current renderer to the matching Puppeteer target.
const result = await SOCIALBROWSER.page.runPuppeteer( async (browser, page, args) => { await page.screenshot({ path: args.path }); return { title: await page.title(), url: page.url(), heading: await page.$eval("h1", node => node.textContent.trim()), }; }, { path: "C:/temp/social-browser-page.png" }, ); console.log(result);The bridge connects Puppeteer with defaultViewport: null and resolves the exact target using the current Chromium debugger target information. The embedded debugger attaches through CDP protocol version 1.3 when needed.
Reliability
Lifecycle and target-selection rules
Find the intended target immediately before use instead of caching a runtime target for a long time.
A restart/reconnect can create new runtime IDs even when the persistent Profile is the same.
Check URL/title/Profile context before sending an action in a multi-Profile session.
Navigation can rebuild a renderer/CDP frame. Your code should wait for the new page state instead of assuming the old frame remains valid.
async function findTargetPage(browser, expectedUrlPrefix) { const pages = await browser.pages(); const page = pages.find(p => p.url().startsWith(expectedUrlPrefix)); if (!page) throw new Error("Target is not available"); return page; } let page = await findTargetPage(browser, "https://example.com/"); await page.goto("https://example.com/dashboard"); // Resolve/validate again when your workflow crosses a restart or reconnect boundary. page = await findTargetPage(browser, "https://example.com/");Errors
Handle failures explicitly
The JavaScript page helpers are designed to fail safely for unavailable targets/actions and commonly resolve to null. Guard important results. The real Puppeteer bridge can also return structured automation errors such as invalid requests, unavailable bridge state, or a missing matching page.
const saveButton = await SOCIALBROWSER.page.click("#save"); if (!saveButton) { console.warn("Save button was not available"); return null; }| Condition | Recommended response |
|---|---|
| Endpoint does not answer | Confirm Social Browser is running and API/debugging access is enabled in API Clients. |
| No matching target | Refresh the live target list; do not reuse an old runtime ID. |
| Selector returns no element | Wait for the expected page state, use a stronger selector, and guard a null result. |
| Navigation replaces the renderer | Wait for navigation/page readiness and resolve the page again when necessary. |
| Puppeteer method unsupported | Use a supported helper/Electron path or another CDP method available in the installed build. |
Security
Developer access is powerful — scope it carefully
- Keep the debugging/API endpoint bound to
127.0.0.1unless you intentionally secure another network path. - Do not publish API keys, client secrets or remote debugging endpoints in source control.
- Treat trusted User Scripts as privileged code; review them before enabling them.
- Use Profile-level separation so automation for one account/workspace does not accidentally act in another.
- Do not expose internal runtime IDs as durable database identifiers.
- Use these capabilities only on systems, pages and accounts you are authorized to operate.