CamouMgr is a desktop manager for Camoufox profiles. It gives you a local UI for creating browser profiles, assigning proxies, choosing an OS fingerprint, launching sessions, and moving profiles in and out of ZIP archives.
The app also starts a small local REST API next to the GUI, so the same profile operations can be scripted.
- Create, edit, rename, and delete profiles.
- Assign a proxy per profile.
- Choose an OS type per profile:
windows,linux, ormacos. - Launch and stop browser sessions from the GUI.
- Select multiple profiles and run bulk launch, stop, or delete actions.
- Check proxy connectivity from the profile dialog.
- Export profiles to ZIP archives, with or without browser data.
- Import profiles from ZIP archives, with optional overwrite behavior.
- View recent activity in the sidebar log and open a larger log window.
- Page through the profile list when you have more than 10 profiles.
- Use the built-in local API for automation.
- Python 3.10 or newer
- A working Python environment that can install the packages in
requirements.txt
The repository includes run_cmngr.bat for Windows. The Python entry point works directly as well.
git clone https://github.com/DedInc/camoumgr.git
cd camoumgr
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux/macOS
source .venv/bin/activate
pip install -r requirements.txtStart the GUI and local API together:
python -m src.mainOn Windows you can also use:
run_cmngr.batWhen the app starts, it launches:
- the Flet desktop UI
- the FastAPI server on
http://127.0.0.1:8000by default
Swagger UI is available at http://127.0.0.1:8000/docs and ReDoc at http://127.0.0.1:8000/redoc.
All configuration is optional. If you want to override defaults, copy .env.example to .env in the project root.
| Variable | Default | Description |
|---|---|---|
CAMOUMGR_PROFILES_FILE |
profiles.json |
JSON file used to store profile metadata. |
CAMOUMGR_DATA_DIR |
camoufox_data |
Directory that stores per-profile browser data. |
CAMOUMGR_LOG_DIR |
logs |
Directory for daily log files. |
CAMOUMGR_LOG_LEVEL |
INFO |
Python log level. |
CAMOUMGR_PROXY_TIMEOUT |
10 |
Default timeout, in seconds, for proxy checks. |
CAMOUMGR_API_HOST |
127.0.0.1 |
Host used by the local API server. |
CAMOUMGR_API_PORT |
8000 |
Port used by the local API server. |
By default, the project writes data to these locations:
profiles.json- profile metadatacamoufox_data\<profile-name>\- browser data for each profilelogs\camoumgr_YYYYMMDD.log- daily log file
Exported ZIP files contain:
profile.jsondata\...when export is run with browser data included
Accepted proxy formats:
host:porthttp://host:porthttps://host:portsocks4://host:portsocks5://host:porthttp://user:pass@host:portsocks5://user:pass@host:port
Rules enforced by the validator:
- scheme is optional
- supported schemes are
http,https,socks4, andsocks5 - port must be in the range
1-65535 - an empty proxy value is allowed
The GUI proxy checker uses the configured timeout and reports either the detected IP or the failure message.
Profile names are validated before they are saved.
- must not be empty
- must be 64 characters or fewer
- must not start or end with spaces
- must not contain
< > : " / \ | ? * - must not be a reserved Windows name such as
CON,PRN,AUX,NUL,COM1-COM9, orLPT1-LPT9
The API is intended for local automation. There is no authentication layer in the code, so leaving it bound to localhost is the safe default.
Base prefix:
/api/v1
| Method | Path | Notes |
|---|---|---|
GET |
/health |
Returns a basic success message. |
Example response:
{
"success": true,
"message": "CamouMgr API is running"
}| Method | Path | Notes |
|---|---|---|
GET |
/profiles |
List all profiles. |
POST |
/profiles |
Create a profile. |
GET |
/profiles/{name} |
Get one profile, including data_dir and is_running. |
PATCH |
/profiles/{name} |
Update only the supplied fields. |
DELETE |
/profiles/{name} |
Delete a profile and its data directory. |
GET |
/profiles/{name}/data-dir |
Return the resolved data directory and whether it exists. |
POST |
/profiles/{name}/export |
Export one profile to a ZIP file. |
POST |
/profiles/import |
Import one profile from a ZIP file. |
Create profile request:
{
"name": "my-profile",
"proxy": "socks5://user:pass@127.0.0.1:1080",
"os_type": "linux"
}Create and update fields:
name: stringproxy: string ornullos_type: string, defaultwindows
Update uses the same fields, but all of them are optional.
Profile response shape:
{
"name": "my-profile",
"proxy": "socks5://user:pass@127.0.0.1:1080",
"os_type": "linux",
"data_dir": "C:\\path\\to\\camoufox_data\\my-profile",
"is_running": false
}Export request:
{
"export_dir": "C:\\Exports",
"include_data": true
}Export response:
{
"success": true,
"zip_path": "C:\\Exports\\my-profile_20260313_134500.zip",
"error": null
}Import request:
{
"zip_path": "C:\\Exports\\my-profile_20260313_134500.zip",
"overwrite": false
}Import response:
{
"success": true,
"profile_name": "my-profile",
"error": null
}Profile endpoint behavior worth knowing:
POST /profilesreturns201 CreatedPATCH /profiles/{name}can return409when a rename conflicts, or when the browser for that profile is running and the name change is blockedDELETE /profiles/{name}returns409if the browser is still runningPOST /profiles/{name}/exportrequiresexport_dirto already existPOST /profiles/importrequiresprofile.jsoninside the ZIP archive
| Method | Path | Notes |
|---|---|---|
GET |
/browser |
List names of running browser sessions. |
GET |
/browser/{name}/status |
Return running status for one profile. |
POST |
/browser/{name}/launch |
Start a browser session asynchronously. |
POST |
/browser/{name}/stop |
Stop a running browser session. |
Running browser response:
{
"running": ["profile-a", "profile-b"],
"count": 2
}Launch response:
{
"success": true,
"message": "Browser launching for 'my-profile'"
}Browser endpoint behavior worth knowing:
POST /browser/{name}/launchreturns202 Accepted- launch is asynchronous; use
GET /browser/{name}/statusorGET /browserto check state POST /browser/{name}/launchreturns409if the profile is already runningPOST /browser/{name}/stopreturns409if the profile is not running
| Method | Path | Notes |
|---|---|---|
POST |
/proxy/check |
Validate and test a proxy. |
Request:
{
"proxy": "socks5://user:pass@127.0.0.1:1080",
"timeout": 10
}Response:
{
"success": true,
"message": "203.0.113.10"
}Create a profile:
curl -X POST http://127.0.0.1:8000/api/v1/profiles ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"work\",\"proxy\":\"socks5://user:pass@127.0.0.1:1080\",\"os_type\":\"linux\"}"Get the resolved data directory:
curl http://127.0.0.1:8000/api/v1/profiles/work/data-dirLaunch a browser:
curl -X POST http://127.0.0.1:8000/api/v1/browser/work/launchCheck whether it is running:
curl http://127.0.0.1:8000/api/v1/browser/work/statusCheck a proxy:
curl -X POST http://127.0.0.1:8000/api/v1/proxy/check ^
-H "Content-Type: application/json" ^
-d "{\"proxy\":\"socks5://user:pass@127.0.0.1:1080\",\"timeout\":10}"src\
api\ FastAPI app, routes, and schemas
core\ config, container, logging, events
interfaces\ service protocols
models\ profile model
services\ profile, browser, and proxy services
ui\ Flet UI, dialogs, and actions
utils\ validation and helper utilities
MIT License