Automation API
Control your Vela Browser programmatically via REST API and real-time WebSocket events. Manage tabs, windows, profiles, fingerprints, and every browser setting from any language or tool.
Authentication
All requests require an API key sent via the X-API-Key header or ?apiKey=YOUR_KEY query parameter.
Default: http://127.0.0.1:1306 — Configure in Settings → Automation
Status
Returns server status, browser version, uptime, and current window/tab counts.
Returns a built-in HTML documentation page. No API key required.
Tabs
Returns all open tabs across all windows. Optionally filter by window ID.
| Param | Description |
|---|---|
| windowId optional | Filter tabs to a specific window |
Returns full details for a specific tab by ID.
Opens a new tab. Optionally specify URL, target window, profile, or private mode.
Closes the specified tab.
Navigates the tab to a new URL.
Reloads the current page in the tab.
Navigate back in history.
Navigate forward in history.
Stops the current page from loading.
Makes this tab the active/selected tab in its window.
Creates a copy of the tab with the same URL.
Toggles the pinned state of the tab.
Toggles the muted state of the tab.
Returns the full HTML source of the current page.
Page Automation
Runs arbitrary JavaScript in the page context and returns the result.
Clicks the first element matching the CSS selector.
Sets the value of an input field using native value setter (compatible with React, Angular, Vue).
Selects an option in a <select> element by value.
Sets the checked state of a checkbox or radio input.
Types text into the focused element with optional per-keystroke delay (simulates real typing).
| Param | Description |
|---|---|
| selector | CSS selector for the target element |
| text | Text to type |
| delay optional | Delay in ms between keystrokes (default: 0) |
Waits until an element matching the selector appears in the DOM (uses MutationObserver).
| Param | Description |
|---|---|
| selector | CSS selector to wait for |
| timeout optional | Timeout in ms (default: 10000) |
Extracts text content or attribute values from one or more elements.
Scrolls to absolute coordinates or to a specific element.
Looks up saved credentials for the domain and auto-fills the login form.
Captures a screenshot of the visible page and returns it as base64-encoded PNG.
Exports the current page as a PDF document returned as base64.
Returns all cookies for the tab's data store.
Sets one or more cookies in the tab's data store.
Removes all cookies from the tab's data store.
Returns the visible text content of the page (innerText of body).
Programmatically sets files on a <input type="file"> element. Files are provided as base64-encoded data. This triggers the change event as if the user selected files via the native file picker.
| Param | Description |
|---|---|
| selector | CSS selector for the file input element |
| files | Array of file objects |
| files[].name | File name (e.g. "report.pdf") |
| files[].data | Base64-encoded file content |
| files[].type optional | MIME type (default: application/octet-stream) |
Windows
Returns all open browser windows.
Returns details for a specific window.
Opens a new browser window, optionally with a specific profile or in private mode. Returns the new window ID and active tab ID.
windowId and tabId reliably.Brings the window to the foreground and activates the Vela app. In headed mode, makes the window the key window and calls NSApplication.activate(ignoringOtherApps: true). In hidden/headless mode this is a no-op.
Closes the specified browser window and all its tabs. Uses a direct NSWindow reference for reliable closing, and always deregisters the window from the API even if the physical close fails.
Window → Active Tab (Convenience)
All tab operations are mirrored at the window level. These endpoints automatically target the window's active tab, so you don't need to look up the tab ID first. Same request/response format as the tab equivalents.
Navigate the window's active tab to a URL. Body: { "url": "https://..." }
Reload the current page on the window's active tab.
Navigate back in the active tab's history.
Navigate forward in the active tab's history.
Stop loading the page on the active tab.
Execute JavaScript on the active tab. Body: { "script": "document.title" }
Click an element. Body: { "selector": "button.submit" }
Fill an input field. Body: { "selector": "input[name='email']", "value": "[email protected]" }
Select a dropdown option. Body: { "selector": "select#country", "value": "US" }
Set checkbox state. Body: { "selector": "#agree", "checked": true }
Type text character by character. Body: { "selector": "#search", "text": "hello", "delay": 50 }
Wait for an element to appear. Body: { "selector": ".loaded", "timeout": 10000 }
Extract text or attributes. Body: { "selector": "h1", "attribute": "textContent", "multiple": false }
Scroll by offset or to element. Body: { "y": 500 } or { "selector": "#footer" }
Fill saved credentials. Body: { "domain": "example.com" }
Capture a screenshot of the active tab as base64 PNG.
Export the active tab as a base64-encoded PDF.
Get cookies for the active tab's current domain.
Set cookies. Body: { "cookies": [{ "name": "...", "value": "...", "domain": "..." }] }
Clear all cookies for the active tab's current domain.
Get all visible text content from the active tab.
Upload files to a file input. Body: { "selector": "input[type=file]", "files": [{ "name": "doc.pdf", "data": "base64...", "type": "application/pdf" }] }
Move mouse cursor with easing on the active tab. Body: { "x": 500, "y": 300 } or { "selector": "#btn" } + optional "duration", "steps", "easing" (ease|linear|human).
Full click sequence on active tab. Body: { "selector": "#btn" } + optional "button" (left|right|middle), "doubleClick".
Dispatches pointerdown + mousedown on the active tab.
Dispatches pointerup + mouseup on the active tab.
Human-like random mouse movement on the active tab. Body: { "duration": 3000 } + optional "area", "speed".
Move along waypoints on the active tab. Body: { "points": [{"x":100,"y":100}, ...], "duration": 1000 }
Profiles
Returns all browser profiles with their configuration.
Returns full details for a specific profile.
Creates a new browser profile with isolated cookies, storage, and fingerprint. Accepts ALL profile settings on creation.
| Param | Description |
|---|---|
| name | Profile name (required) |
| icon optional | SF Symbol name (person.circle, briefcase, house, cart, etc.) |
| color optional | Hex color (e.g. #4A90D9) |
| proxyConfig optional | Per-profile proxy: type (HTTP/SOCKS5), host, port, username, password, isEnabled |
| dnsProvider optional | DNS: system, cloudflare, google, quad9, adguard, opendns, cleanbrowsing, nextdns |
| sessionCookies optional | Array of cookies to store with the profile |
| privacy flags optional | contentBlockerEnabled, blockTrackers, blockAds, blockPopups, httpsFirstEnabled, torEnabled |
| autofillEnabled optional | Enable/disable password autofill for this profile (null = use global) |
| savePasswordEnabled optional | Enable/disable save-password prompts for this profile (null = use global) |
| spoofLanguage optional | Override navigator.languages / Accept-Language, e.g. "en-US,en" or "fr-FR,fr" (null = use browser default) |
| spoofTimezone optional | Override reported timezone via Intl/Date APIs, e.g. "America/New_York" or "Europe/Paris" (null = use system timezone) |
Partially update any profile field (name, icon, color, UA, fingerprint, proxy, DNS, privacy settings).
Deletes a profile. Cannot delete the default profile.
Switches a window to use this profile.
Creates a copy of the profile with a new fingerprint seed.
Generates a new random fingerprint seed for the profile.
User Agents
Returns all available user agent presets organized by category (Desktop, Mobile, Bots, etc.).
Returns the currently active global user agent.
Fingerprints
Returns the fingerprint configuration for a specific profile.
| Param | Description |
|---|---|
| enabled optional | Enable/disable fingerprint protection |
| seed optional | Integer seed for deterministic fingerprint values |
| spoofLanguage optional | Override navigator.languages, e.g. "en-US,en" (null to clear) |
| spoofTimezone optional | Override timezone via Intl/Date APIs, e.g. "America/New_York" (null to clear) |
Generates a new random fingerprint seed for the profile.
Settings
Returns all vela_* UserDefaults settings as key-value pairs.
Returns the value for a single setting key.
Bookmarks
Returns all bookmarks. Optionally filter by folder.
| Param | Description |
|---|---|
| folderId optional | Filter to a specific folder |
Update a bookmark's title, URL, or folder.
Removes a bookmark.
Returns all bookmark folders.
Removes a bookmark folder.
History
| Param | Description |
|---|---|
| limit optional | Max results (default: 100) |
| query optional | Search text filter |
Returns the most frequently visited sites.
Permanently deletes all browsing history.
Removes a single history entry by ID.
Downloads
Returns details for a single download including progress, state, and byte counts.
Starts downloading a file from the given URL.
| Param | Description |
|---|---|
| url | URL of the file to download |
| fileName optional | Custom file name (defaults to URL's last path component) |
Pauses an in-progress download. The download can be resumed later with the resume endpoint.
Resumes a paused download from where it left off.
Cancels an in-progress download or removes a completed one.
Passwords
Lists all saved credentials. Passwords are not included in the response for security.
Returns the full credential including password. Requires the X-Password-Access: true header for additional security.
Profile Autofill
Returns autofill and save-password settings for a specific profile. null values mean the profile uses the global setting.
Enable or disable autofill and save-password prompts for a specific profile. Pass resetToGlobal: true to clear overrides and inherit global settings.
| Param | Description |
|---|---|
| autofillEnabled optional | Enable/disable password autofill for this profile |
| savePasswordEnabled optional | Enable/disable save-password prompts for this profile |
| resetToGlobal optional | Set to true to clear overrides and use global settings |
Content Blocker
Note: extraBlockTrackers enables 80+ additional tracker domains. extraBlockAds enables 60+ additional ad networks. Both are off by default. automaticCookieConsent handles cookie consent dialogs on supported sites.
Profile Cookies
Returns all session cookies stored in the profile configuration.
Replaces all stored session cookies for the profile.
Removes all stored session cookies from the profile.
Takes the profile's stored session cookies and injects them into the live WKWebsiteDataStore, making them immediately available to web pages.
Returns all cookies currently in the profile's live data store (not just stored ones). Optionally filter by domain.
| Param | Description |
|---|---|
| domain optional | Filter cookies to a specific domain |
Profile Export / Import
Exports a complete profile including all settings, proxy config, DNS, privacy flags, session cookies, and ALL live cookies from the data store. The output can be fed directly into the import endpoint.
Creates a new profile from JSON data (same format as export). Live cookies are injected into the new profile's data store.
Downloads a profile ZIP from a remote URL (Dropbox, Google Drive, direct links) and imports it.
Profile Size & Data
Returns the number of data records, cookies, and data type breakdown for a profile's storage.
Removes ALL browsing data for the profile (cookies, cache, local storage, indexed databases, etc.).
Profile Permissions / Privacy
Returns all privacy/permission settings for the profile. null values mean the profile inherits the global setting.
Update privacy/permission settings for the profile. Pass "resetToGlobal": true to clear all overrides and use global settings.
Global Proxy
Returns the global proxy configuration (applies to profiles without their own proxy).
Update the global proxy configuration. All fields are optional (partial update).
Global DNS
Returns the current DNS provider and lists all available providers with details.
Changes the global DNS provider.
| Valid providers | DNS Servers |
|---|---|
| system | OS/router default |
| cloudflare | 1.1.1.1, 1.0.0.1 |
| 8.8.8.8, 8.8.4.4 | |
| quad9 | 9.9.9.9, 149.112.112.112 |
| adguard | 94.140.14.14, 94.140.15.15 |
| opendns | 208.67.222.222, 208.67.220.220 |
| cleanbrowsing | 185.228.168.9, 185.228.169.9 |
| nextdns | 45.90.28.0, 45.90.30.0 |
Measures the latency to a specific DNS provider in milliseconds.
Tests latency for all DNS providers, sorted by fastest first.
Tor
Returns comprehensive Tor status including connection state, SOCKS proxy details, and circuit info.
Requests a new Tor circuit (new exit IP). Tor must be connected. Sends SIGNAL NEWNYM to the Tor control port.
Mouse Simulation
Smoothly moves the simulated mouse cursor to a target position or CSS selector. Dispatches pointermove and mousemove events along the path. Supports multiple easing modes including human-like movement with random jitter.
| Param | Type | Description |
|---|---|---|
| x | number | Target X coordinate (or use selector) |
| y | number | Target Y coordinate (or use selector) |
| selector | string | CSS selector — moves to element center (alternative to x/y) |
| duration | number | Movement duration in ms (default: 100) |
| steps | number | Number of intermediate steps (default: 10) |
| easing | string | "linear", "ease", or "human" (adds ±3px jitter) |
Dispatches a complete click event sequence at the target: pointerdown → mousedown → pointerup → mouseup → click. Optionally fires dblclick for double-click.
| Param | Type | Description |
|---|---|---|
| x / y | number | Target coordinates (or use selector) |
| selector | string | CSS selector — clicks element center |
| button | string | "left" (default), "right", or "middle" |
| doubleClick | boolean | Also fire dblclick event (default: false) |
Dispatches pointerdown and mousedown events at the target position. Use with /mouse/up for drag operations.
Dispatches pointerup and mouseup events at the target position. Use after /mouse/down to complete drag operations.
Generates random human-like mouse movements for a specified duration. Moves between random targets within a bounding area with ease-in-out curves and micro-jitter. Useful for anti-detection and making automated sessions appear natural.
| Param | Type | Description |
|---|---|---|
| duration | number | How long to move in milliseconds (required) |
| area | object | Bounding box { x, y, width, height } — defaults to viewport |
| speed | string | "slow" (80ms), "normal" (40ms), or "fast" (20ms) step intervals |
Moves the mouse cursor along a sequence of waypoints with proportional timing based on segment distances. Each segment uses the specified easing function.
| Param | Type | Description |
|---|---|---|
| points | array | Array of { x, y } waypoints (minimum 2, required) |
| duration | number | Total duration in ms (default: 500) |
| easing | string | "linear", "ease", or "human" |
Element Queries
Check if an element is visible (has dimensions, not hidden/display:none).
Check if an element is not disabled.
Check the checked state of an input element.
Inverse of visible — returns true if element has no dimensions or is hidden.
Count elements matching the selector.
Returns x, y, width, height, top, right, bottom, left.
Returns the innerHTML of the first matching element.
Returns the rendered innerText of the element.
Returns the raw textContent of the element (includes hidden text).
Get a specific attribute value.
Take a screenshot of a specific element (base64 PNG). macOS only.
Element Actions
Dispatch pointerenter/mouseover/mouseenter events on element center.
Call el.focus() on the matched element.
Dispatch full mousedown/mouseup/click/dblclick sequence.
Dispatch keydown/keypress/keyup on element or active element.
Set checked=false and dispatch change event.
Returns document.documentElement.outerHTML.
Returns the current tab title.
Keyboard Input
Dispatch keydown/keypress/keyup on the active element.
Insert text using execCommand or value setter.
Dispatch keydown only.
Dispatch keyup only.
Dispatch WheelEvent.
Native OS Input
Dispatch input via macOS native events — produces isTrusted: true events that are indistinguishable from real user input.
In headed mode, uses CGEvent (native OS events posted to screen coordinates). In hidden/headless mode, injects NSEvent directly into the WKWebView — still produces isTrusted: true events without needing a visible window.
All modes now return "native": true. Safe for 20+ concurrent hidden instances (pasteboard access is serialized).
Headed mode requires Accessibility permission (System Settings > Privacy & Security > Accessibility).
Click an element or coordinates using real OS input events. The element is scrolled into view first. In headed mode, the window is activated and a CGEvent mouse click is posted at screen coordinates. In hidden/headless mode, an NSEvent is injected directly into the WKWebView (still isTrusted:true). Both modes work reliably for concurrent instances.
Type text character by character using real OS keyboard events. Each keystroke produces isTrusted: true. Optional selector focuses the element first. Delay controls milliseconds between keystrokes.
Press a key with optional modifiers using real OS keyboard events. Supports: Enter, Tab, Escape, Backspace, Space, Arrow keys, F1-F12, Home, End, PageUp, PageDown, all letters and digits. Modifiers: Command, Control, Shift, Alt/Option.
Sets the system clipboard with text (and optionally HTML), then sends a real Cmd+V keystroke. In headed mode, activates the window and uses CGEvent. In hidden/headless mode, injects NSEvent Cmd+V directly into the WKWebView (still isTrusted:true). Pasteboard access is serialized for safe use with 20+ concurrent hidden instances.
Move the mouse cursor using OS events with smooth interpolation (ease-in-out). Steps controls intermediate points, duration is total time in ms.
localStorage / sessionStorage
Get a value from localStorage.
Remove a key from localStorage.
Clear all localStorage entries.
Get a value from sessionStorage.
Set a value in sessionStorage.
Remove a key from sessionStorage.
Clear all sessionStorage entries.
Wait Functions
Polls a JS expression until it returns a truthy value. Max timeout: 300s.
Simple sleep/delay. Max: 300s.
Polls until the tab URL changes and loading completes.
Wait for "load", "domcontentloaded", or "networkidle" state.
Polls until the tab URL contains the given pattern.
Frames
Enumerate all frames with index, name, and URL. Cross-origin frames show "(cross-origin)".
Run JavaScript in a specific same-origin frame by index. Returns 403 for cross-origin frames.
Click an element within a same-origin child frame. Returns 403 for cross-origin frames.
Accessibility
Walk the DOM tree and return roles, aria labels, text content, IDs, and class names as a nested JSON tree.
Emulation
Override navigator.geolocation for the tab.
Override Intl.DateTimeFormat timezone.
Override navigator.language and navigator.languages.
Force light or dark mode for the page.
Dialog Handling
Set how alerts/confirms/prompts are handled.
Check if there is a dialog waiting for resolution.
Accept the pending dialog (OK/Yes). Optionally provide promptText for prompt dialogs.
Dismiss the pending dialog (Cancel/No).
Network Monitoring
Monkey-patches fetch() and XMLHttpRequest to log all requests with URL, method, status, and timing.
Returns logged requests. Use ?clear=true to clear the log after reading.
Clear network log and disable monitoring.
Console Capture
Intercepts console.log, warn, error, and info. Also captures uncaught JS errors.
Returns captured console entries. Filter with ?level=error or clear with ?clear=true.
Clear console log and stop capturing.
Tracing
Start a trace session. Returns a traceId to use with stop.
Stop the trace and return all recorded actions with timestamps.
WebSocket Events
Connect via WebSocket to receive real-time browser events. API key is passed as a query parameter.
| Event | Description |
|---|---|
| tab.created | A new tab was opened |
| tab.closed | A tab was closed |
| tab.activated | Active tab changed |
| tab.updated | Tab title or URL changed |
| page.loading | Page started loading |
| page.loaded | Page finished loading |
| page.progress | Page load progress updated |
| navigation.changed | URL changed in a tab |
| window.opened | A new window was opened |
| window.closed | A window was closed |
| profile.switched | Window switched to a different profile |
| download.started | A download began |
| download.completed | A download finished |
| download.failed | A download failed |
| console.log | Console log captured |
| console.warn | Console warning captured |
| console.error | Console error captured |
| js.error | Uncaught JavaScript error |
| dialog.opened | A dialog (alert/confirm/prompt) appeared |
| dialog.closed | A dialog was accepted or dismissed |
| network.request | A network request was initiated |
| network.response | A network response was received |
Hidden & Headless Mode
Run Vela without a visible UI on macOS — no windows, no Dock icon, just the full Automation API. Perfect for CI/CD pipelines, automated testing, web scraping, and server-side browser control.
Hidden Mode (Recommended)
Runs a full headed browser with real GUI rendering, but all windows are invisible. Sessions, cookies, and localStorage persist normally. Websites cannot detect hidden mode since it uses the exact same rendering pipeline as headed mode.
The -g flag prevents bringing the app to the foreground.
Hidden mode defaults to port 1307 (GUI uses 1306) so both APIs run without conflict.
Sessions and cookies persist exactly like headed mode.
Headless Mode (Persistent)
Runs without any visible UI — no dock icon, no windows. WebKit is pre-warmed for fast startup. When a profile is used, sessions are fully persistent (cookies, localStorage, etc.) — like Chrome's headless mode. Without a profile, uses non-persistent storage (ephemeral sessions).
Or run the binary directly:
Optional Flags
| --port <number> | Override API port (default: 1307 hidden/headless, 1306 normal) |
| --bind <address> | Override bind address (default: 127.0.0.1). Use 0.0.0.0 for network access. |
Stdout Output
When launched, connection details are printed to stdout for easy parsing:
Example: Hidden Mode Automation
Python Example
Note: All 175+ API endpoints work identically in hidden, headless, and normal mode.
Stop with pkill -f "Vela.*--hidden", pkill -f "Vela.*--headless", or kill <pid>.