npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

clonbrowser-client

v0.2.0

Published

Unofficial fully typed client for ClonBrowser authentication, proxies, and profiles.

Readme

clonbrowser-client

An unofficial, fully typed TypeScript client for ClonBrowser dashboard authentication, proxy management, and profile management.

[!IMPORTANT] This package wraps the private dashboard gateway observed in ClonBrowser 6.3.6. It is not ClonBrowser's local OpenAPI, is not affiliated with ClonBrowser, and may require updates when the desktop application changes.

Requirements

  • Node.js 20 or newer
  • A ClonBrowser account authorized to manage the relevant proxies and profiles

Installation

npm install clonbrowser-client

Login

import { ClonBrowserClient } from "clonbrowser-client";

const client = await ClonBrowserClient.login({
  authId: process.env.CLONBROWSER_AUTH_ID!,
  password: process.env.CLONBROWSER_PASSWORD!,
});

The client generates a device UUID and reuses it for authenticated requests. Persist both token and deviceId if you need to recreate the session later:

const session = {
  token: client.token,
  deviceId: client.deviceId,
  clientVersion: client.clientVersion,
};

const restoredClient = new ClonBrowserClient(session);

// Uses the same HEAD request observed when the desktop app restores a session.
await restoredClient.validateToken();

You can provide a stable device UUID during login:

const client = await ClonBrowserClient.login(
  { authId, password },
  { deviceId: "00000000-0000-4000-8000-000000000000" },
);

If ClonBrowser requires phone binding, a PIN, or two-factor authentication, login throws ClonBrowserAuthenticationChallengeError with typed challenge fields. This initial client reports the challenge but does not complete the secondary flow.

Proxy management

List proxies

const page = await client.proxies.list({
  page: 1,
  size: 50,
  groupId: "group-id",
});

for (const proxy of page.items) {
  console.log(proxy.proxyId, proxy.address, proxy.port);
}

The optional search list setting is ClonBrowser's raw dashboard sort/filter expression, not a plain-text search term. Omit it to use the captured dashboard ordering.

Get a proxy

const proxy = await client.proxies.get("proxy-id");

Create a proxy

const { guid } = await client.proxies.create({
  address: "proxy.example.com",
  port: 8443,
  proxyType: "https",
  username: "proxy-user",
  password: "proxy-password",
  alias: "Primary proxy",
  remark: "Managed by our application",
  groupIds: [],
  tagIds: [],
});

expiredTime, when provided, is the Unix timestamp in seconds used by the ClonBrowser dashboard.

Update a proxy

The dashboard update endpoint expects a complete proxy definition:

const updated = await client.proxies.update("proxy-id", {
  address: "new-proxy.example.com",
  port: 9443,
  proxyType: "https",
  username: "new-user",
  password: "new-password",
  alias: "Updated proxy",
  remark: "Updated by our application",
});

Delete a proxy

await client.proxies.delete("proxy-id");

// Delete even when ClonBrowser considers the proxy to be in use.
await client.proxies.delete("proxy-id", { force: true });

Profile management

List and get profiles

const page = await client.profiles.list({
  page: 1,
  size: 50,
  groupId: "group-id",
});

const profile = await client.profiles.get(page.items[0]!.guid);

As with proxy lists, omit search to use the dashboard's captured sort expression.

Create a profile

The client asks ClonBrowser's cloud gateway to generate a matching fingerprint template before creating the profile:

const { guid: profileId } = await client.profiles.create({
  name: "Managed profile",
  systemOS: "windows",
  systemVersions: ["11"],
  kernelBrand: "chrome",
  kernelVersion: 149,
  region: "andorra_la_vella",
  proxyId: "proxy-id",
  remark: "Managed by our application",
  defaultUrls: ["https://example.com"],
  settings: {
    cookieSync: true,
    enableBrowserWorkbenchPage: true,
  },
});

Profile settings, fingerprint overrides, accounts, proxy binding, URLs, tags, and returned profile data are fully typed. ClonBrowser can add supported operating systems, regions, kernels, and enum values over time, so the corresponding string types remain forward-compatible.

Edit a profile

Updates are partial at the SDK boundary. The client first retrieves the current profile and then sends the complete PUT payload required by the dashboard, preserving settings you did not change:

await client.profiles.update(profileId, {
  name: "Renamed profile",
  remark: "Updated by our application",
  proxyId: "another-proxy-id",
  settings: {
    cookieSync: false,
  },
});

// Set proxyId to null to remove the profile's proxy binding.
await client.profiles.update(profileId, { proxyId: null });

Update profile cookies

ClonBrowser's cloud profile update accepts its cookie-import payload as a string:

const cookieImport = JSON.stringify([
  {
    domain: ".example.com",
    name: "session",
    value: process.env.EXAMPLE_SESSION_COOKIE!,
  },
]);

await client.profiles.updateCookies(profileId, cookieImport);

The cloud profile-detail response does not return cookie data, so the SDK intentionally does not expose getCookies().

Delete a profile

await client.profiles.delete(profileId);

Existing tokens and configuration

const client = new ClonBrowserClient({
  token,
  deviceId,
  clientVersion: "6.3.6",
  language: "en-US",
  baseUrl: "https://gateway.clonbrowser.com/cb/app",
});

clientVersion, language, and baseUrl have defaults and normally do not need to be supplied. The fetch option accepts a fully typed Fetch-compatible implementation for testing or controlled runtimes.

Errors

Non-successful HTTP responses throw ClonBrowserApiError:

import { ClonBrowserApiError } from "clonbrowser-client";

try {
  await client.proxies.get("missing-proxy");
} catch (error) {
  if (error instanceof ClonBrowserApiError) {
    console.error(error.status, error.method, error.responseBody);
  }
}

Request bodies and credentials are deliberately not attached to errors.

Security

Tokens, account passwords, proxy credentials, profile account credentials, and cookies are secrets. Do not log them or commit them to source control. This client does not persist credentials, tokens, or cookies.

End-to-end testing

The live test exercises login, token validation, and every proxy and profile operation against a dedicated ClonBrowser test account:

CLONBROWSER_E2E_EMAIL="[email protected]" \
CLONBROWSER_E2E_PASSWORD="test-password" \
npm run test:e2e

The GitHub Actions E2E job runs after compatibility and package-quality checks on every push to main. Configure these repository secrets:

  • CLONBROWSER_E2E_EMAIL
  • CLONBROWSER_E2E_PASSWORD

The test treats all pre-existing account data as read-only. It mutates only IDs returned by its own create calls, records those IDs in a per-run ownership set, and verifies a unique ownership marker before every update or deletion. A finally cleanup deletes owned profiles before owned proxies, including when an assertion or request fails. Runs are serialized so two CI jobs cannot operate on the test account concurrently.

Automated releases

After the complete CI workflow succeeds for a push to main, semantic-release determines the next version from Conventional Commits, publishes the package to npm, creates the GitHub release, and tags the tested revision. Documentation and CI-only commits do not publish a new package unless another releasable commit is present.

Publishing uses npm trusted publishing rather than a long-lived npm token. Configure the clonbrowser-client package's trusted publisher on npm with:

  • Provider: GitHub Actions
  • Organization: SimCall
  • Repository: clonbrowser-client
  • Workflow filename: release.yml
  • Allowed action: npm publish

The release workflow uses Node.js 24.10 and npm 11.8, satisfying npm's OIDC requirements. No NPM_TOKEN repository secret is needed.

License

MIT