
Threat Research
/Security News
Searchjacked: Hidden Browser Extensions Hijack Searches for 13 Million Users
319 browser extensions installed by 13.4 million users hijack searches, capture queries, and collect referral payments from Yahoo and Bing.
@scalebrowser/sdk
Advanced tools
Official Node/TypeScript SDK for the Scalebrowser daemon: typed REST client plus a direct-CDP driver plane (nodriver-style, not Playwright).
Official Node / TypeScript SDK for the Scalebrowser daemon: a typed REST client plus a direct-CDP driver plane.
The driver plane is deliberately direct-CDP (nodriver-style), not Playwright /
Puppeteer: anti-bot stacks block the Playwright control plane independently of
how good the browser patches are, so this SDK speaks the Chrome DevTools
Protocol over a raw websocket and never calls Runtime.enable.
npm install @scalebrowser/sdk
Ships dual ESM + CJS with full type declarations, and needs Node ≥ 18. The SDK is MIT-licensed; the daemon it talks to is a separate, licensed product.
import { ScalebrowserClient } from '@scalebrowser/sdk';
const sb = new ScalebrowserClient({
baseUrl: 'http://127.0.0.1:8787', // daemon native API (default)
token: process.env.SCALEBROWSER_TOKEN,
});
// Create a coherent, per-seed-unlinkable profile.
const profile = await sb.createProfile({ name: 'acct-01' });
// Start it + open a direct-CDP session. `await using` stops the profile and
// closes CDP when the block exits.
await using session = await sb.launch(profile.id, { headless: true });
await session.cdp.navigate('https://example.com');
const title = await session.cdp.evaluate<string>('document.title');
// Humanized, trusted input is routed through the daemon (real OS/CDP events).
await session.cdp.humanizeMove(120, 220);
await session.cdp.humanizeClick(120, 220);
Without await using (or for explicit control):
const { cdp_ws } = await sb.startProfile(profile.id, { headless: true });
const cdp = await sb.connectCdp(cdp_ws, profile.id);
try {
await cdp.navigate('https://example.com');
} finally {
cdp.close();
await sb.stopProfile(profile.id);
}
Every /v1 endpoint is a typed method on ScalebrowserClient:
listProfiles, getProfile, createProfile, updateProfile,
deleteProfile, startProfile, stopProfilebulkCreateProfiles, bulkStart, bulkStop, bulkDelete,
bulkAssignProxylistGroups/createGroup/getGroup/updateGroup/deleteGroup,
listPresets/createPreset/getPreset/updatePreset/deletePreset,
getPersonaConstraints. A preset is config (what the profiles do:
geo_mode, proxy_id, …) plus constraints (what they are: country, which
pins the persona's language, timezone and voices). Both are typed and the daemon
refuses an unknown key with a 400, so read the valid regions from
getPersonaConstraints() rather than hardcoding them.listProxies, createProxy, getProxy, updateProxy,
deleteProxy, checkProxy, checkProxyConfig (probe a config before you save
it; pass id to reuse an existing proxy's stored credentials). Credentials
are write-only, never returnedlistExtensions, attachExtension, detachExtension, plus
the daemon-wide library (uploadExtension, getLibraryExtension,
deleteLibraryExtension). An attached package IS loaded into the browser at
launch, under the canonical Web-Store id its own key deriveslistCredentials, putCredential, revealCredential
(needs the vault password), exportCredentials, importCredentialsrevealCookies, the one route a cookie VALUE leaves through,
behind the same vault passwordexportSession, importSessionlistInboxes, createInbox, updateInbox, deleteInbox,
getInboxBindings, bindInbox, unbindInbox, which is where a profile's
confirmation codes arrivelistPasskeys, deletePasskey. Metadata only: the private key
has no field and no endpointlistRuns, getRun, listRunSteps, getRunShot,
getActivity. Read-only, all of itlistInterruptionLocks, setInterruptionLock,
listInterruptionRules, setInterruptionRule, deleteInterruptionRule: who
may answer when the browser asks somethingputArtifact (hand the daemon a file to upload later),
getArtifact (fetch a screenshot, download or saved PDF as bytes)sendInputgetMetrics, getAccount, health, ready.
The first two answer 404 on a daemon without them, which the SDK treats as
information rather than as an error: metrics are then derived from profile
state, and the account reads licensed: false, which is what "self-hosted, no
control plane" meansErrors map to typed exceptions carrying the daemon's numeric code (4001–4012):
import { ApiError, ErrorCode } from '@scalebrowser/sdk';
try {
await sb.startProfile(id);
} catch (err) {
if (err instanceof ApiError && err.code === ErrorCode.Capacity) {
// 4003: capacity exceeded
}
}
// callback form
const unsubscribe = sb.subscribeEvents({
onEvent: (e) => {
if (e.type === 'profile_crashed') console.warn(e.profile_id, e.reason);
},
});
// or async-iterator form
for await (const e of sb.events()) {
if (e.type === 'profile_started') console.log(e.cdp_ws);
}
CdpSession (returned by connectCdp / launch) gives you:
send<T>(method, params?): raw CDP command, awaited by id (concurrent-safe)navigate(url, { wait, timeout }), evaluate<T>(expr, { isolated })createIsolatedWorld(frameId?, worldName?)attachToPage({ targetId?, create?, url? })on(method, cb) / events(): CDP event subscription scoped to the sessionhumanizeMove / humanizeClick / humanizeType / humanizeScrollclose()200, measured, so the engine drops any connection whose peer process runs as
a different user. Nothing to configure and nothing to pass: your process is the
one that started the profile, so it is on the allowed side. A helper running as
another account will not get in, by design.npm install
npm run typecheck # tsc --noEmit (strict)
npm run build # tsup → dist/ (ESM + CJS + .d.ts)
npm test # vitest (unit; e2e skipped unless SCALEBROWSER_E2E=1)
The env-gated end-to-end test runs the full path against a real daemon + mock engine:
SCALEBROWSER_E2E=1 SCALEBROWSER_BASE_URL=http://127.0.0.1:8787 \
SCALEBROWSER_TOKEN=… npm test
FAQs
Official Node/TypeScript SDK for the Scalebrowser daemon: typed REST client plus a direct-CDP driver plane (nodriver-style, not Playwright).
The npm package @scalebrowser/sdk receives a total of 259 weekly downloads. As such, @scalebrowser/sdk popularity was classified as not popular.
We found that @scalebrowser/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Threat Research
/Security News
319 browser extensions installed by 13.4 million users hijack searches, capture queries, and collect referral payments from Yahoo and Bing.

Threat Research
Malicious Firefox extensions mimic Phantom, Jupiter, and Bitget wallets to steal recovery phrases and private keys, with one fetching its payload remotely.

Product
Socket Threat Intel now shows which malware campaigns were blocked or detected in your organization, with links to scans and Firewall events.