Instance Management
Section titled “Instance Management”The browser instance management endpoints let you create, restart, and stop isolated browser instances inside a Hoody container. Use /start to launch or fetch an instance by its browser_id, /restart to recycle an instance with new configuration, and /stop to terminate it and release resources. Each instance is identified by a 0-based browser_id and can run concurrently with other instances. Responses include Chrome DevTools metadata (such as webSocketDebuggerUrl) for remote debugging.
All three endpoints target the same browser service host. Replace {projectId}, {containerId}, and {server} with your project id, container id, and server node.
Create or retrieve instance
Section titled “Create or retrieve instance”GET /start
Section titled “GET /start”Creates a new browser instance or returns metadata for an existing one. This is the primary endpoint for explicitly creating browser instances. The response includes the webSocketDebuggerUrl field, which provides the Chrome DevTools WebSocket endpoint for remote debugging (when available with useRemoteDebuggingPort: true).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
browser_id | query | string | Yes | Unique identifier for the browser instance (0-based index) |
chromiumVersion | query | string | No | Chromium/Chrome version selection for the instance. Applies only when browser=chromium. Supported formats: full version 136.0.7103.113, major version 136, channel tag stable, beta, dev, canary. The server blocks until the required browser is downloaded into BROWSERS_DIR. |
fingerprintId | query | string | No | Base fingerprint profile id. The server loads storage/config/fingerprints/<fingerprintId>.json and uses its context and launch defaults, then applies any request overrides. |
useRemoteDebuggingPort | query | boolean | No | If true, the child process launches Chromium with --remote-debugging-port and populates webSocketDebuggerUrl in metadata responses. Default: true. |
remoteDebuggingPort | query | integer | No | Optional fixed DevTools port (only used when useRemoteDebuggingPort=true). If omitted, a free port is chosen. |
remoteDebuggingAddress | query | string | No | Interface address for DevTools. Defaults to 127.0.0.1. Use 0.0.0.0 only in trusted environments. |
extensions | query | string | No | Comma-separated list (or JSON array string) of absolute extension directory paths to load. Requires showBrowser=true (headful mode) and launches a persistent profile. |
extensionsDir | query | string | No | Directory containing extension subfolders to load (each subfolder is treated as an extension). Requires showBrowser=true (headful mode). |
extensionsStoreIds | query | string | No | Comma-separated list (or JSON array string) of Chrome Web Store extension IDs to download and load. Requires showBrowser=true and works only with browser=chromium. |
proxyServer | query | string | No | Proxy server URL (http, https, socks5, socks5h). Example: socks5://127.0.0.1:9050. |
proxyUsername | query | string | No | Proxy username (if required) |
proxyPassword | query | string | No | Proxy password (if required) |
proxyBypass | query | string | No | Comma-separated list of hosts that should bypass the proxy |
enableQuic | query | boolean | No | Enable QUIC/HTTP3 transport. Defaults to false (QUIC blocked). Default: false. |
enableDnsOverHttps | query | boolean | No | Enable DNS-over-HTTPS for browser DNS resolution. Default: true. |
dnsOverHttpsUrl | query | string | No | DoH resolver URL (HTTPS only). Defaults to Cloudflare. Default: "https://cloudflare-dns.com/dns-query". |
display | query | integer | string | No | X display number or identifier for headful mode. Required when showBrowser=true and no DISPLAY environment variable is set on the server. |
showBrowser | query | boolean | No | Whether to run the browser headful (visible). Default: true. |
sessionName | query | string | No | Custom session name for identifying this browser instance |
timezoneId | query | string | No | IANA timezone identifier for browser geolocation |
locale | query | string | No | BCP 47 language tag for browser locale |
userAgent | query | string | No | User agent string to apply to the browser context |
viewport | query | string | No | Viewport configuration as JSON string. Example: {"width":1920,"height":1080,"deviceScaleFactor":1}. Pass null to disable fixed-viewport emulation entirely — the page then follows the real browser window size. |
noViewport | query | boolean | No | Set to true to disable fixed-viewport emulation (alias for viewport=null). Cannot be combined with a fixed viewport object. Default: false. |
geolocation | query | string | No | Geolocation configuration as JSON string. Example: {"latitude":40.7128,"longitude":-74.0060,"accuracy":100}. |
stealth | query | boolean | No | Launch Chromium in stealth mode using Patchright (anti-detection patches). Applies only to browser=chromium; ignored for Firefox. Default: true. Bare ?stealth is treated as true. |
iframe | query | boolean | No | Enable or disable the full-page display iframe on the root URL. When enabled (default), navigating to / serves an HTML page with an iframe pointing to the Hoody display URL. Default: true. |
iframe_url | query | string | No | Explicit URL for the display iframe. If not provided, the URL is auto-detected from the Host header subdomain pattern. |
maximize_new_windows | query | boolean | No | Control the maximize_new_windows flag stamped onto generated display URLs. When true, the hoody-display client opens new top-level app windows maximized. Default: true. |
Request body
Section titled “Request body”This endpoint takes no request body.
Response
Section titled “Response”{ "engine": "patchright", "stealth": true, "headless": false, "chromiumBuildId": "136.0.7103.113", "chromiumExecutablePath": "/hoody/storage/hoody-browser/chrome/chrome/linux-136.0.7103.113/chrome-linux64/chrome", "browserExecutablePath": "/hoody/storage/hoody-browser/chrome/chrome/linux-136.0.7103.113/chrome-linux64/chrome", "fingerprintId": "default", "display": ":0", "iframe_url": "https://67e89abc123def456789abcd-890abcdef12345678901cdef-browser-display-1.node-us.containers.hoody.com", "browser_id": "0", "browser_host": "67e89abc123def456789abcd-890abcdef12345678901cdef-browser-1", "browser_port": 9222, "sessionId": "b6e7d6f4-8d1e-4f3a-9b2c-1d4e5f6g7h8i", "sessionName": "primary", "timezoneId": "America/New_York", "locale": "en-US", "geolocation": { "latitude": 40.7128, "longitude": -74.0060, "accuracy": 100 }, "viewport": { "width": 1920, "height": 1080, "deviceScaleFactor": 1 }, "viewportSource": "creation", "userAgentString": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.113 Safari/537.36", "browserName": "chromium", "browserFullVersion": "136.0.7103.113", "operatingSystemName": "Linux", "operatingSystemPlatform": "Linux x86_64", "operatingSystemVersion": "6.5.0", "renderingEngine": "Blink", "renderingEngineVersion": "136.0.7103.113", "webSocketDebuggerUrl": "ws://67e89abc123def456789abcd-890abcdef12345678901cdef-cdp-1.node-us.containers.hoody.com/devtools/browser/b6e7d6f4-8d1e-4f3a-9b2c-1d4e5f6g7h8i", "devtoolsHttpUrl": "http://67e89abc123def456789abcd-890abcdef12345678901cdef-cdp-1.node-us.containers.hoody.com/json/version", "devtoolsFrontendUrl": "https://67e89abc123def456789abcd-890abcdef12345678901cdef-cdp-1.node-us.containers.hoody.com", "extensions": [], "useRemoteDebuggingPort": true, "remoteDebuggingPort": 9222, "remoteDebuggingAddress": "0.0.0.0", "quicDisabled": true, "http3Disabled": true, "dnsOverHttpsEnabled": true, "dnsOverHttpsUrl": "https://cloudflare-dns.com/dns-query", "tabs": [ { "id": 1, "url": "about:blank" } ]}{ "error": "Invalid browser_id", "code": "INVALID_BROWSER_ID", "details": { "browser_id": "must be a non-negative integer" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Validation Error | One or more request parameters failed validation | Check the error details for the specific parameter and constraint that failed |
INVALID_BROWSER_ID | Invalid Browser ID | The browser_id value is invalid | Provide a valid browser_id |
{ "error": "Existing instance uses a different stealth backend", "code": "INSTANCE_BACKEND_MISMATCH", "details": { "existingBackend": "playwright", "requestedBackend": "patchright" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSTANCE_BACKEND_MISMATCH | Instance Backend Mismatch | The existing instance was launched with a different stealth mode/backend | Stop the running instance first, then start again with the new stealth mode |
{ "error": "Chrome binary not found at expected path", "code": "CHROME_NOT_FOUND", "details": { "chromiumVersion": "136.0.7103.113", "searchedPath": "/hoody/storage/hoody-browser/chrome/chrome/linux-136.0.7103.113/chrome-linux64/chrome" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSTANCE_CREATE_FAILED | Instance Creation Failed | The browser instance could not be created | Check server logs for details. Ensure sufficient system resources are available |
CHROME_NOT_FOUND | Chrome Not Found | The Chrome/Chromium binary was not found at the expected path | Ensure Chrome is installed or provide a valid chromiumVersion parameter to trigger download |
SDK usage
Section titled “SDK usage”import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-browser-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.browser.instances.start({ browser_id: '0' });curl -G "https://{projectId}-{containerId}-browser-1.{server}.containers.hoody.com/start" \ --data-urlencode "browser_id=0"Restart instance
Section titled “Restart instance”GET /restart
Section titled “GET /restart”Stops and recreates a browser instance using the provided configuration. Accepts the same parameters as /start, plus a few engine-specific options (browser, firefoxVersion, firefoxExecutablePath, showDevtools, userProfile, launchArguments).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
browser_id | query | string | Yes | Unique identifier for the browser instance (0-based index) |
chromiumVersion | query | string | No | Chromium/Chrome version selection for the instance. Applies only when browser=chromium. Supported formats: full version 136.0.7103.113, major version 136, channel tag stable, beta, dev, canary. The server blocks until the required browser is downloaded into BROWSERS_DIR. |
fingerprintId | query | string | No | Base fingerprint profile id. The server loads storage/config/fingerprints/<fingerprintId>.json and uses its context and launch defaults, then applies any request overrides. |
useRemoteDebuggingPort | query | boolean | No | If true, the child process launches Chromium with --remote-debugging-port and populates webSocketDebuggerUrl in metadata responses. Default: true. |
remoteDebuggingPort | query | integer | No | Optional fixed DevTools port (only used when useRemoteDebuggingPort=true). If omitted, a free port is chosen. |
remoteDebuggingAddress | query | string | No | Interface address for DevTools. Defaults to 127.0.0.1. Use 0.0.0.0 only in trusted environments. |
extensions | query | string | No | Comma-separated list (or JSON array string) of absolute extension directory paths to load. Requires showBrowser=true (headful mode) and launches a persistent profile. |
extensionsDir | query | string | No | Directory containing extension subfolders to load (each subfolder is treated as an extension). Requires showBrowser=true (headful mode). |
extensionsStoreIds | query | string | No | Comma-separated list (or JSON array string) of Chrome Web Store extension IDs to download and load. Requires showBrowser=true and works only with browser=chromium. |
proxyServer | query | string | No | Proxy server URL (http, https, socks5, socks5h) |
proxyUsername | query | string | No | Proxy username (if required) |
proxyPassword | query | string | No | Proxy password (if required) |
proxyBypass | query | string | No | Comma-separated list of hosts that should bypass the proxy |
enableQuic | query | boolean | No | Enable QUIC/HTTP3 transport. Defaults to false (QUIC blocked). Default: false. |
enableDnsOverHttps | query | boolean | No | Enable DNS-over-HTTPS for browser DNS resolution. Default: true. |
dnsOverHttpsUrl | query | string | No | DoH resolver URL (HTTPS only). Defaults to Cloudflare. Default: "https://cloudflare-dns.com/dns-query". |
display | query | integer | string | No | X display number or identifier for headful mode. Required when showBrowser=true and no DISPLAY environment variable is set on the server. |
showBrowser | query | boolean | No | Whether to run the browser headful (visible). Default: true. |
sessionName | query | string | No | Custom session name for identifying this browser instance |
timezoneId | query | string | No | IANA timezone identifier for browser geolocation |
locale | query | string | No | BCP 47 language tag for browser locale |
userAgent | query | string | No | User agent string to apply to the browser context |
viewport | query | browser_Viewport | No | Viewport configuration as JSON string. Example: {"width":1920,"height":1080,"deviceScaleFactor":1}. Pass null to disable fixed-viewport emulation entirely — the page then follows the real browser window size. |
noViewport | query | boolean | No | Set to true to disable fixed-viewport emulation (alias for viewport=null). Cannot be combined with a fixed viewport object. Default: false. |
geolocation | query | browser_Geolocation | No | Geolocation configuration as JSON string. Example: {"latitude":40.7128,"longitude":-74.0060,"accuracy":100}. |
launchArguments | query | array | No | Additional browser launch arguments (repeatable or JSON array) |
browser | query | string | No | Browser engine to use (chromium or firefox). Default: "chromium". |
firefoxVersion | query | string | No | Firefox version label (informational only). Playwright-managed Firefox builds are used by default. If omitted, a Playwright Firefox build is downloaded on demand. |
firefoxExecutablePath | query | string | No | Absolute path to a custom Firefox executable (overrides download) |
showDevtools | query | boolean | No | Whether to open DevTools on launch (Chromium only). Default: false. |
userProfile | query | object | No | Optional user profile object (JSON string) for fingerprinting defaults |
stealth | query | boolean | No | Launch Chromium in stealth mode using Patchright (anti-detection patches). Applies only to browser=chromium; ignored for Firefox. Default: true. Bare ?stealth is treated as true. |
iframe | query | boolean | No | Enable or disable the full-page display iframe on the root URL. Default: true. |
iframe_url | query | string | No | Explicit URL for the display iframe. |
maximize_new_windows | query | boolean | No | Control the maximize_new_windows flag stamped onto the generated display URL. When true, the hoody-display client opens new top-level app windows maximized. Default: true. |
Request body
Section titled “Request body”This endpoint takes no request body.
Response
Section titled “Response”{ "message": "Restarted", "meta": { "engine": "patchright", "stealth": true, "headless": false, "chromiumBuildId": "136.0.7103.113", "chromiumExecutablePath": "/hoody/storage/hoody-browser/chrome/chrome/linux-136.0.7103.113/chrome-linux64/chrome", "browserExecutablePath": "/hoody/storage/hoody-browser/chrome/chrome/linux-136.0.7103.113/chrome-linux64/chrome", "fingerprintId": "default", "display": ":0", "browser_id": "0", "browser_host": "67e89abc123def456789abcd-890abcdef12345678901cdef-browser-1", "browser_port": 9222, "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "sessionName": "primary", "timezoneId": "America/New_York", "locale": "en-US", "geolocation": { "latitude": 40.7128, "longitude": -74.0060, "accuracy": 100 }, "viewport": { "width": 1920, "height": 1080, "deviceScaleFactor": 1 }, "viewportSource": "creation", "userAgentString": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.113 Safari/537.36", "browserName": "chromium", "browserFullVersion": "136.0.7103.113", "operatingSystemName": "Linux", "operatingSystemPlatform": "Linux x86_64", "operatingSystemVersion": "6.5.0", "renderingEngine": "Blink", "renderingEngineVersion": "136.0.7103.113", "webSocketDebuggerUrl": "ws://67e89abc123def456789abcd-890abcdef12345678901cdef-cdp-1.node-us.containers.hoody.com/devtools/browser/a1b2c3d4-e5f6-7890-abcd-ef1234567890", "useRemoteDebuggingPort": true, "remoteDebuggingPort": 9222, "remoteDebuggingAddress": "0.0.0.0", "quicDisabled": true, "http3Disabled": true, "dnsOverHttpsEnabled": true, "dnsOverHttpsUrl": "https://cloudflare-dns.com/dns-query", "tabs": [ { "id": 1, "url": "about:blank" } ] }}{ "error": "One or more parameters failed validation", "code": "VALIDATION_ERROR", "details": { "parameter": "remoteDebuggingPort", "constraint": "must be an integer in the range 1-65535" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Validation Error | One or more request parameters failed validation | Check the error details for the specific parameter and constraint that failed |
{ "error": "No browser instance exists for browser_id 7", "code": "INSTANCE_NOT_FOUND", "details": { "browser_id": "7" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSTANCE_NOT_FOUND | Instance Not Found | No browser instance exists for the specified browser_id | Verify the browser_id value, or create a new instance using /start |
{ "error": "Existing instance uses a different stealth backend", "code": "INSTANCE_BACKEND_MISMATCH", "details": { "existingBackend": "playwright", "requestedBackend": "patchright" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSTANCE_BACKEND_MISMATCH | Instance Backend Mismatch | The existing instance was launched with a different stealth mode/backend | Stop the running instance first, then start again with the new stealth mode |
{ "error": "Browser instance could not be restarted", "code": "RESTART_FAILED", "details": { "browser_id": "0", "stage": "spawn" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESTART_FAILED | Restart Failed | The browser instance could not be restarted | Check server logs for details. The instance may need to be manually stopped and recreated |
SDK usage
Section titled “SDK usage”import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-browser-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.browser.instances.restart({ browser_id: '0', stealth: true });curl -G "https://{projectId}-{containerId}-browser-1.{server}.containers.hoody.com/restart" \ --data-urlencode "browser_id=0" \ --data-urlencode "stealth=true"Stop instance
Section titled “Stop instance”GET /stop
Section titled “GET /stop”Stops an active browser instance for the provided browser_id. This terminates the child process and releases its resources.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
browser_id | query | string | Yes | Unique identifier for the browser instance (0-based index) |
Request body
Section titled “Request body”This endpoint takes no request body.
Response
Section titled “Response”{ "message": "Stopped", "meta": { "browser_id": "0", "engine": "patchright", "stealth": true, "headless": false, "chromiumBuildId": "136.0.7103.113", "browser_host": "67e89abc123def456789abcd-890abcdef12345678901cdef-browser-1", "browser_port": 9222, "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "sessionName": "primary", "browserName": "chromium", "browserFullVersion": "136.0.7103.113", "tabs": [ { "id": 1, "url": "about:blank" } ] }}{ "error": "No browser instance exists for browser_id 7", "code": "INSTANCE_NOT_FOUND", "details": { "browser_id": "7" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSTANCE_NOT_FOUND | Instance Not Found | No browser instance exists for the specified browser_id | Verify the browser_id value, or create a new instance using /start |
SDK usage
Section titled “SDK usage”import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-browser-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.browser.instances.stop({ browser_id: '0' });curl -G "https://{projectId}-{containerId}-browser-1.{server}.containers.hoody.com/stop" \ --data-urlencode "browser_id=0"