What Can You Do With the BitBrowser API?
The BitBrowser API is a local HTTP interface that lets your own scripts create, launch, list and close browser profiles on a machine where BitBrowser is installed and signed in. You send JSON with POST, read a success/data/msg envelope, and keep every request local. It suits repeatable QA setups, onboarding workflows and profile housekeeping on accounts you own or are authorised to manage.

📌 TL;DR Executive Summary
- Core Takeaway: The BitBrowser API is a localhost POST API. Wrap it in one helper that checks
success, then call/browser/update,/browser/open,/browser/listand/browser/close. - Key Risk/Challenge: Connection refused,
success:falseresponses and profiles stuck in opening or closing state come from a closed client, a wrong port, bad parameters or a close call that never ran. - Recommended Solution: Launch with
queue:true, close every profile infinally, paginate past 100 profiles and respect free-plan daily quotas before you batch anything.
Prerequisites Before You Call a Single Endpoint
The Local API is a feature of the running desktop client, not a remote service you can reach from a cold machine. Install BitBrowser, sign in, then open Settings and copy the Local API URL and port. Community references commonly show http://127.0.0.1:54345, but the value your own client displays is the one that works. If nothing answers on that port, the app is closed, signed out, or the Local API is disabled for your account.
- Client: 64-bit Windows 10 or later, or macOS 12 Monterey or later on Apple Silicon or Intel. Windows needs a 4-core CPU, 8 GB RAM and 50 GB free disk. Keep the app open while your script runs.
- Local API access: enabled in Settings. The main account turns it on unless sub-accounts are granted permission, and changing the API key means stopping and restarting the local service.
- Python: Python 3.9 or newer with the
requestslibrary (pip install requests). - Capacity: the free tier gives 10 profiles, 1 member, 50 opens a day and 20 creates a day. Paid tiers raise profile and seat counts; check what they say about daily behaviour before you size a job.
- Permission boundary: use the API only with accounts you own or are authorised to manage. Where a platform limits multiple accounts, take its official route — Amazon approval for an extra seller account, Meta Business Manager roles for agencies. A script is not a way around limits, verification or enforcement.
If you are still deciding whether BitBrowser fits the team, the BitBrowser review covers profile limits and collaboration before you build around the API.
Step 1: Build One Helper and Prove the Connection
Write one helper instead of scattering requests.post through the file. Every call is POST with JSON in the body and JSON back. An HTTP 200 does not mean the operation worked, so check success before you touch data, and surface msg when it is false.
import requests
BASE = "http://127.0.0.1:54345"
def api(path, payload=None):
response = requests.post(f"{BASE}{path}", json=payload or {}, timeout=30)
response.raise_for_status()
body = response.json()
if not body.get("success"):
raise RuntimeError(body.get("msg", "BitBrowser API request failed"))
return body.get("data")
if __name__ == "__main__":
print(api("/browser/list", {"page": 0, "pageSize": 1}))
Run it once with a real profile in the client. A data object means your URL, port and login state are correct. A connection error means fix the client first. An exception carrying msg means the service answered and the payload or permissions are wrong. The official repo ships JavaScript, Python and Postman demos, and a community TypeScript SDK on npm (bitbrowser, published January 2026) wraps the same endpoints if you would rather write JavaScript.
| Task | Endpoint | Important parameters |
|---|---|---|
| Create a profile | POST /browser/update | No id creates a new profile |
| Update selected fields | POST /browser/update/partial | Send only the fields you want to change |
| Launch a profile | POST /browser/open | id, args, queue |
| List profiles | POST /browser/list | page starts at 0; pageSize maximum is 100 |
| Close a profile | POST /browser/close | id |
| Reset a stuck window state | POST /users | Only after a normal close attempt fails |
For the wider lifecycle outside this specific API, the guide to a browser profile API explains how creation, launch and cleanup fit together.
Step 2: Create a Profile With Documented Fields
POST /browser/update creates a profile when no id is supplied. The payload below sticks to documented fields — name, remark, proxy type, cookie and storage sync flags, and the clear-cookies switch — and uses noproxy so no real proxy password ends up in a tutorial file.
def create_profile(name):
payload = {
"name": name,
"remark": "Created by the local API tutorial",
"proxyType": "noproxy",
"syncCookies": True,
"syncIndexedDb": True,
"syncLocalStorage": True,
"clearCookiesBeforeLaunch": False,
}
return api("/browser/update", payload)
proxyType accepts noproxy, http, https, socks5 and ssh. When you add a proxy, map host, port, username and password exactly as the profile reference names them and load the values from the environment. Leave clearCookiesBeforeLaunch false when the profile must keep its own session; set it true only for a deliberate clean start. Print the create response once so you can see which key in the data object holds the new profile id.
To change one setting later, call POST /browser/update/partial and send only those fields, so you do not overwrite the proxy and sync settings you spent time getting right. On Windows 7, Windows 8 or Server 2012 the client cannot run kernel 109 or above; set coreVersion to 104 on those systems or the profile may fail to open.
Step 3: Launch With queue:true and Take the CDP URL
POST /browser/open takes the profile id, an optional args array and queue:true. Use the queue flag whenever a script opens more than one profile: the local service serialises launches instead of answering with concurrency errors when several opens land at the same moment.
def launch_profile(profile_id, headless=False):
payload = {"id": profile_id, "queue": True}
if headless:
payload["args"] = ["--headless"]
return api("/browser/open", payload)
The open response carries a WebSocket URL for the launched window. Print the data object once, note the key that holds that URL, and hand the value to your framework. The local API also exposes windows, tabs, groups and headless mode, and BitBrowser documents Selenium and Puppeteer integration. Use those attachments for your own QA pages and authorised workflows, not to scrape sites against their terms.
Headless launches are fine for smoke tests, but they hide layout bugs and render at default sizes. For anything visual, open a normal window and arrange geometry afterwards with POST /windowbounds, which lays out windows using col, spaceX and spaceY, with a minimum width of 500 and minimum height of 200. A third-party guide puts the practical ceiling at roughly 8 to 12 concurrent Chromium profiles on a 16 GB machine, which is a better planning number than the profile count on your plan.
Need the handshake in detail? This walkthrough on how to connect Playwright to a virtual browser API shows how a runner attaches over CDP once it has that URL.
Step 4: List, Close and Recover Profiles
POST /browser/list pages from page 0 with pageSize capped at 100, and filters on groupId, name, remark and seq. Paginate explicitly: a script that reads one page silently ignores profiles once the account passes 100. Close with POST /browser/close inside a finally block, because an unclosed profile is the usual reason a later launch reports that it is already running.
def list_profiles(page=0, page_size=50):
if page_size not in range(1, 101):
raise ValueError("pageSize must be between 1 and 100")
return api("/browser/list", {"page": page, "pageSize": page_size})
def close_profile(profile_id):
return api("/browser/close", {"id": profile_id})
def reset_window_state():
return api("/users", {})
If a close fails and the profile sits in opening or closing state, call POST /users once, wait a few seconds and retry. Do not loop the reset endpoint. POST /browser/delete exists too, but keep deletion out of routine cleanup until you have logged and verified the ids you are removing.
close_profile() in a finally block and send queue:true on every open. Those two habits remove most stuck-profile and concurrency errors from batch scripts before they happen.
Step 5: Batch Create Profiles From a CSV
A CSV import is a loop around the create call. Start with a name column and an optional remark, keep proxy secrets out of the file, and cap the rows to what your plan allows today — 20 creates a day on the free tier means a 50-row file fails partway through unless you split it.
import csv
def create_from_csv(path):
created_ids = []
with open(path, newline="", encoding="utf-8") as handle:
for row in csv.DictReader(handle):
name = row.get("name", "").strip()
if not name:
continue
data = api("/browser/update", {
"name": name,
"remark": row.get("remark", "CSV import"),
"proxyType": "noproxy",
"syncCookies": True,
"syncIndexedDb": True,
"syncLocalStorage": True,
"clearCookiesBeforeLaunch": False,
})
if isinstance(data, dict) and data:
created_ids.append(data)
return created_ids
Validate the proxy type before the first request — one bad proxyType wastes the entire run — and append results to a log file as you go, so a failure halfway down the file does not leave you guessing which profiles already exist. If a row carries proxy details, map only the fields the profile reference documents and load the credentials from environment variables.
BitBrowser Plans and What They Mean for a Script
Scripts fail on quotas long before they fail on code. Published plan summaries put the free tier at 10 profiles, 1 member, 50 opens a day and 20 creates a day, with Local API access, RPA, extensions and team permissions included. Paid tiers are sold by profile count and seats rather than by API calls.
| Plan (published summary) | Profiles | Members | Notes |
|---|---|---|---|
| Free | 10 | 1 | 50 opens/day, 20 creates/day, Local API included |
| $10/month | 50 | 2 | Higher profile ceiling for solo work |
| $15/month | 100 | 4 | Small team tier |
| $25/month | 200 | 8 | Largest published tier |
Daily open and create limits are published for the free tier; the paid tiers publish profile and seat counts, so confirm current limits on the vendor’s page before you size a nightly job. BitBrowser’s year-end sale runs November 11 to December 12, 2026, with 20% off 3-month, 30% off 6-month, 40% off 12-month and 50% off 24-month terms — relevant if you are about to pay annually for a batch job. The BitBrowser pricing breakdown compares what each tier actually includes.
Common BitBrowser API Errors and Fixes
Connection refused on the local port
The client is closed, signed out, the Local API is off, the port is wrong, or your sub-account lacks permission. Open BitBrowser, sign in, check Settings and confirm the port the client displays. Community references note that the service must be running under a signed-in account.
success:false with a msg field
Read msg before changing code at random. Usual causes are a missing profile id, an unsupported proxyType, a field sent to the wrong endpoint, a pageSize above 100, or a sub-account without Local API permission. Log the endpoint and a redacted payload, never the proxy password.
Profile stuck in opening or closing state
Attempt a normal close first, then the POST /users reset from Step 4, waiting between attempts. Repeated opens without matching closes create this state faster than concurrency does, so check your finally block before you blame the API.
Profiles fail to open on older Windows
Windows 7, Windows 8 and Server 2012 cannot run kernel 109 or above, so set coreVersion to 104. If the machine does not meet the client requirements at all, move the script to a supported Windows 10+ or macOS 12+ system rather than fighting the kernel.
Batch runs hit a plan quota
The free tier allows 50 opens and 20 creates a day. Add backoff, split large CSVs across days, and confirm paid-tier limits with the vendor before a production run. A quota stop returns success:false with a message, not a crash.
Full Script: Create, Launch, List and Close
The script below combines the helper and the create, launch, list and close functions. It creates one profile, opens it with queue:true, prints the open response and a small page of profiles, then closes the profile in finally. It deletes nothing. Run it against a test profile before you point it at a working set.
import time
import requests
BASE = "http://127.0.0.1:54345"
def api(path, payload=None):
response = requests.post(f"{BASE}{path}", json=payload or {}, timeout=30)
response.raise_for_status()
body = response.json()
if not body.get("success"):
raise RuntimeError(body.get("msg", "BitBrowser API request failed"))
return body.get("data")
def profile_id_from(data):
if isinstance(data, dict):
for key in ("id", "browserId"):
if data.get(key):
return data[key]
if isinstance(data, str) and data:
return data
raise RuntimeError(f"No profile id in response: {data!r}")
def create_profile(name):
payload = {
"name": name,
"remark": "Created by the local API tutorial",
"proxyType": "noproxy",
"syncCookies": True,
"syncIndexedDb": True,
"syncLocalStorage": True,
"clearCookiesBeforeLaunch": False,
}
return api("/browser/update", payload)
def launch_profile(profile_id, headless=False):
payload = {"id": profile_id, "queue": True}
if headless:
payload["args"] = ["--headless"]
return api("/browser/open", payload)
def list_profiles(page=0, page_size=50):
if not 1 <= page_size <= 100:
raise ValueError("pageSize must be between 1 and 100")
return api("/browser/list", {"page": page, "pageSize": page_size})
def close_profile(profile_id):
return api("/browser/close", {"id": profile_id})
def reset_window_state():
return api("/users", {})
def main():
created = create_profile(f"api-demo-{int(time.time())}")
profile_id = profile_id_from(created)
print(f"Created profile {profile_id}")
try:
opened = launch_profile(profile_id)
print(f"Open response: {opened}")
print(f"Profiles on page 0: {list_profiles(page_size=10)}")
finally:
close_profile(profile_id)
print(f"Closed profile {profile_id}")
if __name__ == "__main__":
main()
Call reset_window_state() by hand only when the close step fails and the profile stays stuck. Keep created ids in your own log if you plan to reopen the same profiles later, and when the script exits on success:false, fix the msg and rerun against a fresh test profile instead of retrying a broken payload in a tight loop.
🏆 Send.win Verdict
Send.win is a browser profile manager — a desktop app for Windows, macOS and Linux plus a cloud browser running on an EU server in Helsinki — where each profile keeps its own cookies, storage, session and fingerprint settings. It offers no automation interface on any plan: no API, SDK, headless mode or Selenium/Puppeteer/Playwright support, so a workflow built on /browser/open belongs to BitBrowser and stays there. Where Send.win fits is the manual side of the same job: sharing a profile with a paid teammate so it opens already signed in, or handing a live cloud session to support staff without passing passwords around.
See Send.win plans — Pro from $19/mo or $6.99/mo billed annually, with a 7-day money-back guarantee on your first card purchase, or the free cloud demo at 10 minutes a day to test the workflow first.
Frequently Asked Questions
What port does the BitBrowser API use?
BitBrowser’s setup guidance points you to the Local API URL and port shown in the client’s Settings. Community references commonly show http://127.0.0.1:54345, but third-party notes go stale, so use the value your installed client displays and never expose that port outside localhost.
Does the BitBrowser API require an API key?
Community references report that the local server binds to localhost and needs no key for local calls, which is worth verifying in your own client rather than assuming. Only the main account can enable the Local API unless sub-accounts are granted permission, and changing the key requires stopping and restarting the local service.
How do I create a browser profile through the API?
Send POST /browser/update with no id and a JSON body of the fields you want, such as name, proxyType and the sync flags. Success returns success:true with a data object; failure returns success:false with a msg. Use /browser/update/partial when you only want to change selected fields later.
Can I connect Playwright or Puppeteer to a BitBrowser profile?
Yes. POST /browser/open returns a WebSocket URL for the launched profile, and a framework can attach to that session over CDP. BitBrowser also documents Selenium and Puppeteer integration plus headless mode. Use it for your own QA and authorised workflows, not for scraping in breach of a site’s terms.
Why does my BitBrowser API request return success false?
The msg field is the fastest clue. Common causes are a missing profile id, an unsupported proxyType, a pageSize above 100, a field sent to the wrong endpoint, or a sub-account without Local API permission. Redact secrets whenever you log a request body.
How do I close or reset a profile stuck in opening state?
Call POST /browser/close with the profile id first. If the profile stays stuck, POST /users resets a window left in opening or closing state. Wait a few seconds before retrying, and use queue:true on later opens so you do not rebuild the same pile-up.
What is included in the BitBrowser free plan?
Published summaries list 10 profiles, 1 member, 50 opens per day, 20 profiles created per day, Local API access, RPA, extensions and scripts, and team permissions. Paid tiers start around $10/month for 50 profiles and 2 users. Confirm current terms on the vendor’s own pricing page.
Can I batch create profiles from a CSV of proxies?
Yes — loop over the CSV and call /browser/update per row, but validate the proxy type and required fields before the first request. On the free tier 20 creates a day is the practical limit, so split large files across days. Use only accounts and proxies you own or are authorised to use.
How Send.win Helps With Bitbrowser Api
Send.win is a browser profile manager for professionals and teams: every account gets its own isolated browser profile.
- Isolated profiles – separate cookies, storage and sessions per profile
- Fingerprint protection – each profile keeps its own consistent browser fingerprint, so profiles never share one browser identity
- Desktop app + cloud browser – native app for Windows, macOS and Linux, or run profiles in the cloud with no install
- Residential proxies included – on Pro and Team, with timezone and locale matched to the proxy
- Team sharing – share a signed-in profile with a teammate without sharing the password
Try the free cloud demo — no install — or download the desktop app. Paid plans start at $19/month, and your first card purchase is covered by a 7-day money-back guarantee (see pricing).