Camoufy Download

HTTP API reference

Camoufy 1.1.1

Everything the interface does goes through this API, so a script can do the same. For a short introduction see HTTP API in the docs.

Basics

On Windows the address is http://127.0.0.1:18800. In Docker it is the address of the interface, for example https://camoufy.example.com. Every path below starts with /api/v1.

Send the key from Settings in one of three ways: the X-Api-Key header, Authorization: Bearer KEY, or ?api_key=KEY in the address. Bodies and answers are JSON unless a row says otherwise.

curl -H "X-Api-Key: $KEY" http://127.0.0.1:18800/api/v1/profiles

An error comes back with an HTTP status and this body:

{"error": {"code": "not_found", "message": "profile not found"}}
StatusCodeMeaning
400bad_requestThe request is wrong. The message says what
401unauthorizedThe key is missing or wrong
403wrong_passwordWrong profile password
404not_foundNo such profile, proxy or file
409runningThe profile has to be stopped first
423lockedThe profile has a password and the request gave none
424no_engineNo engine is installed

Profiles

RequestWhat it does
GET /profilesList profiles. Filters: q (name, notes, id, tag, proxy, country, IP), tag, status (running, stopped or an exact status). Answer: {profiles, running, total}
POST /profilesCreate a profile from the fields below. Answer 201: {profile, fingerprint}
GET /profiles/{id}One profile with its fingerprint and the geo data of its last start
PATCH /profiles/{id}Change name, tags, notes, proxy, addons, launch or geo. Only the keys you send are applied. The proxy of a running profile cannot be changed, and os never can
DELETE /profiles/{id}Delete a stopped profile with its cookies and data
POST /profiles/{id}/cloneCopy a profile. Body: {name, with_cookies, keep_fingerprint}. Answer 201: {profile}
POST /profiles/bulkOne action over many profiles. Body: {action, ids} with action start, stop, delete, add_tag, remove_tag or set_proxy, plus tag, proxy_id or headless where the action needs it. Answer: {results}, "ok" or an error text for each id

Fields of a profile:

FieldValue
name, notes, tagsText, text and a list of strings
oswindows, macos or linux. The fingerprint is generated for it. Default windows
proxy{"mode": "none"}, {"mode": "list", "proxy_id": "..."} or {"mode": "tor", "tor_exit": "de"}. The exit country is optional
addonsList of add-on ids from the library
launchstart_urls, restore_session, headless_default, free_window (the window may grow beyond the screen of the fingerprint), theme (system, dark or light. The browser theme that sites see as prefers-color-scheme. Default system follows the computer the browser runs on), extra_prefs (Firefox preferences)
geo{"mode": "auto"} follows the exit IP of the proxy. "manual" takes override: {timezone, locale, lat, lon}. "off" leaves geo alone
password, unlock_toOnly when creating. A password protects the profile at once. unlock_to is disk or memory
curl -H "X-Api-Key: $KEY" -X POST http://127.0.0.1:18800/api/v1/profiles -d '{"name": "Shop DE", "os": "windows", "tags": ["shop"], "proxy": {"mode": "list", "proxy_id": "px_41c0aa"}}'

In answers a profile also carries id, created_at, updated_at, last_started_at, encrypted, status (the run state below), fingerprint (a summary) and proxy_info.

Start and stop

RequestWhat it does
POST /profiles/{id}/startStart the browser. Body, all optional: headless, urls, automation ("bidi" opens a WebDriver BiDi endpoint), password for a protected profile. Answer: the run state
POST /profiles/{id}/stopClose the browser and wait until its data is saved. {"force": true} ends the process at once. Answer: the run state
POST /profiles/{id}/open-urlOpen {"url": "..."} in a new tab of a running profile
GET /profiles/{id}/tabsOpen tabs as the browser last saved them: {tabs: [{window, index, url, title, active}]}. The browser saves its tabs every 15 seconds, so the list lags behind and is empty right after a start
POST /profiles/{id}/proxy/rotateNew sticky session on a proxy with {session}, or a new Tor circuit. Works on a running profile
POST /profiles/{id}/new-identityMake a profile a new person. wipe erases the whole browser folder, bookmarks, saved logins and add-on data and settings included. It is the default when the body names no data part below. Body, each part true unless set to false. Browser data, cleared selectively when wipe is false: cookies, history (visits, forms, downloads, back and forward of tabs), site_data (localStorage, IndexedDB, service workers), tabs (open and recently closed) and cache. data sets all five at once. Firefox clears them itself during a few seconds of a start without a window and without network, so bookmarks, saved logins and add-on data stay. fingerprint draws a new one. proxy changes the IP. A proxy with {session} gets a new session, Tor builds new circuits, a plain proxy is swapped for a free working one from the list. Browser data and fingerprint need a stopped profile. A running profile can still get a new IP from a {session} proxy or Tor. A protected profile needs password to clear data selectively, a wipe needs none. Answer: profile, wiped, cleared, plus fingerprint and proxy: {changed, mode, proxy_id, session_id, note} for the parts done
GET /profiles/{id}/logThe end of the profile log as plain text, up to 256 KB

The run state:

FieldValue
statusstopped, starting, running, running_external (started from a launch recipe), proxy_error or crashed
pid, started_at, stopped_atProcess id and times
headless, screenWhether it runs headless, and whether it has a virtual screen (Docker)
ws_endpointLocal BiDi address, with automation "bidi"
remote_wsPath of the same endpoint through the server, see below
bytes_in, bytes_outTraffic through the proxy of the profile
error, exit_codeWhy it stopped, if it did not stop cleanly
engine, proxy_id, dropped_keysEngine version in use, proxy in use, fingerprint keys this engine does not know

Automation

RequestWhat it does
GET /profiles/{id}/bidiWebSocket to the BiDi endpoint of a profile started with automation "bidi". Use the remote_ws path from the start answer. For a profile with a password it carries a token of that run
GET /profiles/{id}/launch-recipeWhat your own Playwright needs to launch the profile: executable_path, user_data_dir, args, env, firefox_user_prefs, proxy, lease_id. Optional ?headless=1. The password of a protected profile goes in the X-Profile-Password header
DELETE /leases/{lease_id}Tell Camoufy the browser from a recipe has closed. Without it the lease ends by itself soon after the browser exits
GET /profiles/{id}/screenWebSocket with the VNC stream of the virtual screen of a profile (Docker). The interface uses it on its Screen page

Three things to know when you write your own BiDi client:

  • Create tabs in the background: browsingContext.create with {"type": "tab", "background": true}. Without background the engine never answers the command.
  • For the tabs open right now ask the browser: browsingContext.getTree. GET /profiles/{id}/tabs reads the saved session and can be 15 seconds behind.
  • The browser allows one BiDi session at a time and keeps it after its client disconnects. The remote_ws connection ends the session for you when you close it or it drops. On the local ws_endpoint send session.end before you close, or the next session.new fails until the profile restarts.

The recipe holds local paths, so it is for scripts on the same machine as Camoufy. From another machine use remote_ws or MCP.

Fingerprint

RequestWhat it does
GET /profiles/{id}/fingerprint{fingerprint, effective, dropped}: the stored fingerprint, the settings the engine receives, and the keys it does not know
PATCH /profiles/{id}/fingerprintReplace your own overrides: {"overrides": {"navigator.hardwareConcurrency": 8}}. An empty object removes them all
POST /profiles/{id}/fingerprint/regenerateNew fingerprint for the same OS. The profile has to be stopped

Cookies, export, password

RequestWhat it does
POST /profiles/{id}/cookies/importPut cookies in Netscape format (cookies.txt) into a stopped profile. Body: {text, password}, or a multipart form with file. ?domain=example.com keeps that domain and its subdomains. Up to 2000 cookies. Answer: {imported, parsed, failed, parse_errors, domains}
POST /profiles/{id}/cookies/exportRead the cookies of a stopped profile. The browser starts without a window for a few seconds. Body, all optional: format ("txt" for Netscape cookies.txt, the default, or "json" in the Cookie-Editor layout), domain to keep one domain and its subdomains, password for a protected profile. Answer: the file, with the count in the X-Cookie-Count header
GET /profiles/{id}/exportDownload a stopped profile as a .cbprofile file. ?proxy=1 adds its proxy with the password, ?addons=1 adds its add-on files
POST /profiles/importMultipart form with one or more file fields. Answer: {results} with a profile or an error for each file
POST /profiles/{id}/passwordOn a stopped profile. Set: {"new": "..."}. Change: {"current": "...", "new": "..."}. Remove: {"current": "...", "new": ""}. unlock_to (disk or memory) says where the data is decrypted at start

Proxies

RequestWhat it does
GET /proxies{proxies}, each with its last check and used_by, the ids of the profiles on it
POST /proxiesAdd one proxy: {type, host, port, username, password, label, tags}. Type is http, https or socks5. Or add a list: {text, tags}, one proxy per line. Answer: {added, total_parsed, proxies, errors}. POST /proxies/import is the same request
POST /proxies/quickCheck one line {text, tags} and add it only if it works. Answer: {ok, proxy, check} or {ok: false, error}
PATCH /proxies/{id}Change label, tags, type, host, port, username or password
DELETE /proxies/{id}Delete a proxy. If a profile uses it, add ?force=1 and that profile is left without a proxy
POST /proxies/deleteDelete many: {ids, force}. Without force, proxies in use answer 409 with used_by
POST /proxies/{id}/checkCheck one proxy now, up to 25 seconds. Answer: {proxy} with last_check: {ok, ip, country, region, city, timezone, latency_ms, error}
POST /proxies/checkCheck many in the background: {ids}, or all with an empty body. Answer 202. Results arrive as proxy.check events

A line of a proxy list can look like any of these. Without a scheme the type is http. Put {session} in the login for sticky sessions.

host:port
host:port:user:pass
host:port:user:pass:socks5
user:pass@host:port
socks5://user:pass@host:port

Add-ons

RequestWhat it does
GET /addons{addons}: id, name, version, description, source, used_by
POST /addons/from-urlAdd from a direct link to an .xpi file: {"url": "..."}. Answer 201: {addon}
POST /addonsUpload .xpi files, a multipart form with one or more file fields
POST /addons/{id}/updateFetch the newest version from addons.mozilla.org or the original link. Answer: {addon, updated, previous, restart}, where restart names the running profiles that still use the old files
DELETE /addons/{id}Remove from the library. If a profile uses it, add ?force=1

An add-on works in a profile once its id is in the addons list of that profile. A link to an add-on from addons.mozilla.org looks like this:

https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi

Engine and Tor

RequestWhat it does
GET /engine{versions, current, dir}: installed Camoufox versions and the one in use
POST /engine/check-updates{releases} available on GitHub, each with name, version, asset_url, asset_size, installed
POST /engine/installInstall a release. The body is one object from check-updates. Answer 202. Progress arrives as engine.progress events, then engine.installed or engine.error
POST /engine/useSwitch to an installed version: {"name": "..."}
POST /engine/importCopy an engine from {"path": "..."} on the machine Camoufy runs on. Answer 202, same events
DELETE /engine/{name}Remove a version. Every profile has to be stopped
GET /tor{tor: {installed, version, tor_version, size_mb, transports}}
POST /tor/installDownload Tor. Optional {"version": "..."}. Answer 202, then tor.progress and tor.installed or tor.error events
DELETE /torRemove Tor. Profiles running through it have to be stopped

Settings and system

RequestWhat it does
GET /settingsAll settings, the API key among them
PATCH /settingsChange any of port, theme (system, light, dark), lang (en, ru), ip_services, check_updates, tor_bridges, show_cursor, browser_ui (firefox, camoufox), and on Windows start_minimized, exit_on_close, minimize_to_tray, autostart, ui_mode
POST /settings/rotate-keyIssue a new API key. The old one stops working at once. The answer holds the new key
GET /systemVersion, OS, folder sizes, number of profiles, running profiles, and whether this copy runs in a container with virtual screens
GET /updateResult of the last update check: {current, result, checking, error}
POST /update/checkCheck camoufy.com for a new version now
POST /system/showBring the program window to the front (Windows)
POST /system/quitStop every profile and close Camoufy

Events

GET /events is a stream of server-sent events. Each one has a name and a JSON body.

curl -N -H "X-Api-Key: $KEY" http://127.0.0.1:18800/api/v1/events
EventWhen
profile.statusThe run state of a profile changed. The body is the new run state
profile.changedA profile was created, updated, deleted or imported
proxy.check, proxy.check.doneOne proxy was checked, and a background check of many has finished
proxy.rotatedA profile got a new sticky session or Tor circuit
proxy.changed, addon.changed, settings.changedThe list or the settings changed
engine.progress, engine.installed, engine.error, engine.changedEngine download, install and switch
tor.progress, tor.installed, tor.errorTor download and install
updateAn update check has finished