Guide
Profiles
A profile is Morrow's unit of identity: a real, persistent Camoufox browser on disk, not a database record.
The persistence model
Each profile is a real Firefox (Camoufox) profile directory on disk, stored under <MORROW_DATA_DIR>/profiles/<id> — cookies, localStorage, IndexedDB, and any signed-in session state for sites the profile has visited. Profile metadata (name, status, proxy, locale, timezone, viewport, timestamps) lives separately in a local SQLite database.
Because the browser directory itself is what persists, stopping a profile flushes cookies and storage to disk, and starting it again resumes exactly where it left off — same fingerprint, same logins, same open state. This is what makes Morrow different from a throwaway headless browser: a profile behaves like a returning human on a real machine, not a fresh instance every run.
Naming
Profile names are lowercase letters, digits, and dashes, and must start with a letter or digit (^[a-z0-9][a-z0-9-]{0,62}$). Names are how you address a profile everywhere — REST paths, the Playwright websocket URL, and MCP tool arguments all take the name, not the internal id.
Lifecycle
All lifecycle endpoints need Authorization: Bearer $MORROW_API_KEY.
Create
curl -X POST http://localhost:3000/api/v1/profiles \
-H "Authorization: Bearer $MORROW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "research-eu", "locale": "de-DE"}'Start
curl -X POST http://localhost:3000/api/v1/profiles/research-eu/start \
-H "Authorization: Bearer $MORROW_API_KEY"Launches the browser. A profile that's already running when a request needs it (Playwright connect, scrape with a profile field, an MCP tool call) auto-starts — you rarely need to call this directly except from the dashboard.
Stop
curl -X POST http://localhost:3000/api/v1/profiles/research-eu/stop \
-H "Authorization: Bearer $MORROW_API_KEY"Flushes browser state to disk and closes the browser process.
Clone
curl -X POST http://localhost:3000/api/v1/profiles/research-eu/clone \
-H "Authorization: Bearer $MORROW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "research-eu-2"}'Copies the source profile's on-disk directory (cookies, storage, logins) and its proxy/locale/timezone/ viewport into a new profile. The source must be stopped first.
Reset
curl -X POST http://localhost:3000/api/v1/profiles/research-eu/reset \
-H "Authorization: Bearer $MORROW_API_KEY"Deletes the profile's on-disk browser directory — cookies, storage, logins, and the pinned fingerprint — while keeping the profile record and its settings. The profile must be stopped first; the next start begins from a clean browser again.
Delete
curl -X DELETE http://localhost:3000/api/v1/profiles/research-eu \
-H "Authorization: Bearer $MORROW_API_KEY"Removes the profile record and its on-disk directory entirely. Irreversible; the profile must be stopped first.
Configuration
Set at create time, or updated later with PATCH /api/v1/profiles/:name (pass null to clear a field):
proxy— a proxy URL this profile's browser routes through, so the network origin matches the persisted identity.locale— e.g.de-DE, baked into the spoofed fingerprint.timezone— e.g.Europe/Berlin.viewport—{ width, height }.
Full request/response shapes are in the OpenAPI reference at /api-docs.
Events timeline
Every profile records events — created, started, stopped, reset, and more — retrievable via GET /api/v1/profiles/:name/events (optionally ?limit=, default 200, max 1000). The dashboard's profile page renders this as a timeline alongside the live viewer, active sessions, and connect snippets.
Concurrency limit
MORROW_MAX_PROFILES caps how many profiles can be running at once (default 5) — not how many profiles can exist. Starting a profile past the limit returns 429 too_many_profiles. See Self-hosting.