Skip to content
Home » DICloak Runtime Image

DICloak Runtime Image

Package the DICloak antidetect browser into a Docker image. Launch a fully fingerprint-spoofed browser environment with a single command — no host-level software installation required. Integrates seamlessly with Playwright and Puppeteer via the standard CDP protocol.

Image: `dicloakinc/dicloak-runtime-image`

Protocol: Chrome DevTools Protocol (CDP)

Concurrency Limit: 100 browser instances

Authentication: Email + Password

Browser Mode: Non-headless (full browser UI)

docker run -d \
  --name dicloak-runtime \
  -e USER_EMAIL=your@email.com \
  -e USER_PASSWD=your_password \
  -e PORT=52140 \
  -e DOCKER=1 \
  -p 52140:52140 \
  -p 127.0.0.1:45000-45099:45000-45099 \
  --shm-size=1g \
  dicloakinc/dicloak-runtime-image:latest

Overview

DICloak Runtime Image is a preconfigured Docker image with the full DICloak antidetect browser runtime built in. It solves a core problem: vanilla headless Chromium produces highly uniform browser fingerprints that are easily flagged as automation by websites.

On startup, the image runs a Local API service (default port 52140) inside the container. Your code interacts with this API to manage browser environments, each with its own unique fingerprint profile. When an environment is opened, a CDP debug port is dynamically assigned for Playwright or Puppeteer to connect to.

The browser runs in non-headless mode with a full UI, behaving identically to a manually operated browser for stronger anti-detection capabilities.

Use Cases

  • AI Agents that need persistent, logged-in browser sessions
  • Automation scripts that need to bypass bot detection
  • Multi-account workflows requiring isolated browser environments
  • CI/CD pipelines that need stable, reproducible browser testing environments

Workflow

1. Pull and start the container — Pass account credentials and port configuration via environment variables. The Local API service starts automatically inside the container.

2. Open a browser environment via the Local API — Send a request to `http://127.0.0.1:52140/openapi/v1/env/{env_id}/open` and receive a CDP debug port (`debug_port`) for that environment.

3. Retrieve the WebSocket debug URL — Request `http://127.0.0.1:{debug_port}/json/version` to get the `webSocketDebuggerUrl`.

4. Connect and run your automation — Use `connectOverCDP(wsUrl)` to connect to the browser. Fingerprinting is handled automatically by DICloak; everything else works exactly like standard Playwright/Puppeteer.

5. Close or reuse the environment — Close the browser instance via the API to release port resources. If a volume is mounted, session data is persisted and automatically restored on next startup.


Prerequisites

System Requirements

ResourceMinimumNotes
CPU2 coresEach concurrent browser instance uses approximately 0.2–0.5 additional cores
Memory4 GBEach active browser instance uses approximately 200–400 MB
Disk10 GBThe image itself is ~3–5 GB; profile data grows on demand
Shared Memory1 GBChrome relies heavily on /dev/shm; insufficient allocation causes rendering crashes. Set via --shm-size=1g
Docker20.10+Latest stable version recommended

DICloak Account & Plan

Before using this image, complete the following steps:

  1. Register an account at dicloak.com

2. Subscribe to the Plus plan or higher — Docker runtime functionality is only available to Plus-tier users and above

3. Obtain your API Key from the Settings → Open API page in the DICloak dashboard

Important Note on Account Types

> It is strongly recommended NOT to use the super admin account registered during sign-up to run Docker.

> The DICloak super admin account uses single sign-on — only one active session is allowed at a time. If you start a Docker container with the super admin account, all other sessions on other devices or browsers will be logged out.

> Best practice: Create a dedicated team member account in the DICloak dashboard for Docker use. Use that member account’s email and password as the container’s credentials. Member accounts are not subject to the single sign-on restriction and will not interfere with the super admin’s sessions.


Quick Start

Step 1: Pull the Image

docker pull dicloakinc/dicloak-runtime-image:latest

Step 2: Start the Container

Replace `your@email.com` and `your_password` with the email and password of your DICloak team member account:

docker run -d \
  --name dicloak-runtime \
  -e USER_EMAIL=your@email.com \
  -e USER_PASSWD=your_password \
  -e PORT=52140 \
  -e DOCKER=1 \
  -p 52140:52140 \
  -p 127.0.0.1:45000-45099:45000-45099 \
  --shm-size=1g \
  dicloakinc/dicloak-runtime-image:latest

Step 3: Verify the Service Is Ready

curl "http://127.0.0.1:52140/openapi/v1/env/list?page_no=1&page_size=1" \
  -H "X-API-KEY: YOUR_API_KEY"

A response containing {"code": 0, ...} confirms the Local API service is running.

> Note: If the container exits immediately after startup, run `docker logs dicloak-runtime` to inspect the logs. The most common causes are incorrect email/password or an account without a Plus subscription.


Environment Variables

Pass via -e KEY=VALUE (docker run) or environment: (Compose).

VariableRequiredDefaultDescription
USER_EMAILYesEmail of the DICloak team member account
USER_PASSWDYesPassword of the DICloak team member account
PORTYes52140Local API listen port. If changed, update the -p port mapping accordingly
DOCKERYesMust be set to 1. Signals the application that it is running inside Docker. Do not omit

Port Mapping

The container uses two sets of ports. Both must be mapped to the host via -p at startup; otherwise, the host cannot reach the services inside the container.

Port Overview

PortDirectionPurpose

| `52140` | Host → Container | Local API port — Manages the lifecycle of browser environments (list, open, close, etc.) |

| `45000–45099` | Host → Container | Browser CDP ports — Each active environment is assigned one port for browser control |

### `-p` Parameter Format

-p [host_bind_address:]host_port:container_port

**`host_bind_address`** (optional): Defaults to `0.0.0.0` (all interfaces) if omitted. Set to `127.0.0.1` to restrict access to localhost only.

**`host_port`**: The port used by external clients (host machine or other services) to connect.

**`container_port`**: The port the service listens on inside the container. Typically matches the container’s internal configuration and does not need to be changed.

Recommended Configuration

# Local API: bind to localhost (when automation scripts run on the same machine)
-p 127.0.0.1:52140:52140

# Browser CDP ports: bind to localhost
-p 127.0.0.1:45000-45099:45000-45099

Cross-Machine Access

If your automation scripts run on a different machine, change the bind address to `0.0.0.0` to expose the ports on external interfaces:

-p 0.0.0.0:52140:52140
-p 0.0.0.0:45000-45099:45000-45099

# Shorthand (omitting the address defaults to 0.0.0.0)
-p 52140:52140
-p 45000-45099:45000-45099

> Security Warning: Exposing ports to the public network is a security risk — anyone who can reach the IP can control the browsers inside the container. Only do this in trusted internal networks, or use a VPN / SSH tunnel for port forwarding.

Port Conflict Resolution

If port 52140 is already in use, change the PORT environment variable and the corresponding host port:

docker run -d \
  -e PORT=52200 \
  -p 127.0.0.1:52200:52200 \
  ...   # remaining parameters unchanged

Find the process occupying the port:

lsof -i :52140            # macOS / Linux
netstat -ano | findstr :52140    # Windows

Data Persistence

By default, all data inside the container (browser profiles, cookies, LocalStorage, fingerprint configurations, etc.) is lost when the container is removed. Mount a volume to persist this data on the host, enabling automatic session restoration after container restarts.

Container PathContents
/root/.config/DICloakCacheBrowser profiles, cookies, session data, fingerprint parameters

Mount Example

docker run -d \
  --name dicloak-runtime \
  -e USER_EMAIL=your@email.com \
  -e USER_PASSWD=your_password \
  -e PORT=52140 \
  -e DOCKER=1 \
  -p 127.0.0.1:52140:52140 \
  -p 127.0.0.1:45000-45099:45000-45099 \
  -v ./data:/root/.config/DICloakCache \
  --shm-size=1g \
  dicloakinc/dicloak-runtime-image:latest

Data is stored in the ./data/ directory on the host. After removing the container or updating the image, remount the same directory to automatically restore all profiles and session state.

> Tip: In production, use an absolute path (e.g., `-v /data/dicloak:/root/.config/DICloakCache`) to avoid data loss caused by working directory changes.


Local API Usage

Browser control in this image relies on the DICloak Local API. After the container starts, the API service listens on the port specified by `PORT`.

Full API reference: DICloak API Developer Guide

Authentication

All requests must include the API Key in the header:

X-API-KEY: YOUR_API_KEY

Obtain the API Key from Settings → Open API in the DICloak dashboard.

Base URL

http://127.0.0.1:52140/openapi

Response Format

// Success
{ "code": 0, "msg": "success", "data": { ... } }

// Failure
{ "code": 500, "msg": "error description" }

Core Endpoints

List Environments

GET /v1/env/list?page_no=1&page_size=20
X-API-KEY: YOUR_API_KEY

Returns all created browser environments and their IDs. Use env_id in subsequent API calls.

Open a Browser Environment

PATCH /v1/env/{env_id}/open
X-API-KEY: YOUR_API_KEY

Example response:

{
  "code": 0,
  "msg": "success",
  "data": {
    "debug_port": 45001
  }
}

The returned debug_port is the CDP debug port for this browser instance, in the 45000–45099 range.

Close a Browser Environment

PATCH /v1/env/{env_id}/close
X-API-KEY: YOUR_API_KEY

Get the CDP WebSocket URL

After opening an environment, request the following endpoint using the debug_port to obtain the WebSocket URL required by Playwright/Puppeteer:

GET http://127.0.0.1:{debug_port}/json/version

Example response:

{
  "webSocketDebuggerUrl": "ws://127.0.0.1:45001/devtools/browser/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Connecting to the Browser

Once you have the webSocketDebuggerUrl, connect directly via Playwright or Puppeteer.

Playwright (JavaScript)

const { chromium } = require('playwright');

// 1. Open the environment and get debug_port
const openRes = await fetch(
  'http://127.0.0.1:52140/openapi/v1/env/YOUR_ENV_ID/open',
  {
    method: 'PATCH',
    headers: { 'X-API-KEY': 'YOUR_API_KEY' },
  },
);
const {
  data: { debug_port },
} = await openRes.json();

// 2. Get the WebSocket debug URL
const versionRes = await fetch(`http://127.0.0.1:${debug_port}/json/version`);
const { webSocketDebuggerUrl } = await versionRes.json();

// 3. Connect to the browser via CDP
const browser = await chromium.connectOverCDP(webSocketDebuggerUrl);
const page = await browser.newPage();

// 4. Use as normal — fingerprinting is handled automatically by DICloak
await page.goto('https://example.com');

// 5. Close the environment when done
await fetch('http://127.0.0.1:52140/openapi/v1/env/YOUR_ENV_ID/close', {
  method: 'PATCH',
  headers: { 'X-API-KEY': 'YOUR_API_KEY' },
});

Playwright (Python)

import requests
from playwright.sync_api import sync_playwright

API_BASE = "http://127.0.0.1:52140/openapi"
API_KEY  = "YOUR_API_KEY"
ENV_ID   = "YOUR_ENV_ID"
HEADERS  = {"X-API-KEY": API_KEY}

# 1. Open the environment and get debug_port
res = requests.patch(f"{API_BASE}/v1/env/{ENV_ID}/open", headers=HEADERS)
debug_port = res.json()["data"]["debug_port"]

# 2. Get the WebSocket debug URL
version = requests.get(f"http://127.0.0.1:{debug_port}/json/version").json()
ws_url = version["webSocketDebuggerUrl"]

# 3. Connect to the browser via CDP
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(ws_url)
    page = browser.new_page()

    # 4. Use as normal
    page.goto("https://example.com")

# 5. Close the environment when done
requests.patch(f"{API_BASE}/v1/env/{ENV_ID}/close", headers=HEADERS)

Puppeteer

const puppeteer = require('puppeteer');

// 1. Open the environment and get debug_port
const openRes = await fetch(
  'http://127.0.0.1:52140/openapi/v1/env/YOUR_ENV_ID/open',
  {
    method: 'PATCH',
    headers: { 'X-API-KEY': 'YOUR_API_KEY' },
  },
);
const {
  data: { debug_port },
} = await openRes.json();

// 2. Get the WebSocket debug URL
const versionRes = await fetch(`http://127.0.0.1:${debug_port}/json/version`);
const { webSocketDebuggerUrl } = await versionRes.json();

// 3. Connect to the browser via CDP
const browser = await puppeteer.connect({
  browserWSEndpoint: webSocketDebuggerUrl,
});
const page = await browser.newPage();

// 4. Use as normal
await page.goto('https://example.com');

// 5. Close the environment when done
await fetch('http://127.0.0.1:52140/openapi/v1/env/YOUR_ENV_ID/close', {
  method: 'PATCH',
  headers: { 'X-API-KEY': 'YOUR_API_KEY' },
});

Production Deployment (Docker Compose)

For production, Docker Compose is recommended for unified configuration management, automatic restarts, data persistence, and easier service scaling.

docker-compose.yml

services:
  dicloak-runtime:
    image: dicloakinc/dicloak-runtime-image:latest
    container_name: dicloak-runtime
    restart: unless-stopped # Auto-restart on crash; no restart on manual stop
    environment:
      USER_EMAIL: ${DICLOAK_EMAIL} # Read from .env file to avoid plaintext secrets in yml
      USER_PASSWD: ${DICLOAK_PASSWD}
      PORT: 52140
      DOCKER: 1
    ports:
      - '127.0.0.1:52140:52140'
      - '127.0.0.1:45000-45099:45000-45099'
    volumes:
      - ./data:/root/.config/DICloakCache
    shm_size: '1gb'

.env File

Store credentials in .env to keep sensitive information out of version control:

# .env
DICLOAK_EMAIL=member@yourcompany.com
DICLOAK_PASSWD=your_member_password

Make sure .env is listed in .gitignore.

Common Compose Commands

# Start in detached mode
docker compose up -d

# Follow live logs
docker compose logs -f

# Stop and remove containers (data in ./data is preserved)
docker compose down

# Update image and redeploy
docker compose pull && docker compose up -d

Container Management

Basic Operations

# Follow live logs
docker logs -f dicloak-runtime

# Stop the container
docker stop dicloak-runtime

# Start a stopped container
docker start dicloak-runtime

# Remove the container (data is preserved in ./data if a volume is mounted)
docker rm -f dicloak-runtime

Updating the Image

# 1. Pull the latest image
docker pull dicloakinc/dicloak-runtime-image:latest

# 2. Remove the old container
docker rm -f dicloak-runtime

# 3. Re-run with the same parameters (data persisted via volume is unaffected)
docker run -d \
  --name dicloak-runtime \
  -e USER_EMAIL=your@email.com \
  -e USER_PASSWD=your_password \
  -e PORT=52140 \
  -e DOCKER=1 \
  -p 127.0.0.1:52140:52140 \
  -p 127.0.0.1:45000-45099:45000-45099 \
  -v ./data:/root/.config/DICloakCache \
  --shm-size=1g \
  dicloakinc/dicloak-runtime-image:latest

Troubleshooting

Container Exits Immediately After Startup

Symptom: Container is not visible in `docker ps`, or STATUS shows Exited.

Diagnose:

docker logs dicloak-runtime

Common causes:

  • Incorrect email or password — authentication failed
  • Account does not have a Plus subscription — no access to Docker runtime
  • Super admin account was used — kicked out by single sign-on (switch to a team member account)
  • Missing -e DOCKER=1 parameter
  • Network issue preventing connection to DICloak servers

API Requests Return 401 / 403

Symptom: Local API requests return authentication errors.

Checklist:

  • Verify the header name is X-API-KEY (case-sensitive)

– Verify the API Key is from Settings → Open API in the DICloak dashboard, not the account password

  • Verify the account has a Plus subscription

Port Already in Use

Symptom: Startup fails with `port is already allocated` or `bind: address already in use`.

Diagnose:

lsof -i :52140            # macOS / Linux
netstat -ano | findstr :52140    # Windows

Solution: Stop the process occupying the port, or change the `PORT` environment variable and the corresponding `-p` mapping.


Browser Instance Crashes or Freezes

Symptom: Browser becomes unresponsive after launch, pages render incorrectly, or container logs show `shared memory` errors.

Solution: Chrome relies heavily on `/dev/shm` (shared memory) for rendering. Ensure your startup command includes `–shm-size=1g`. For higher concurrency, increase the value accordingly (e.g., `–shm-size=2g`).

# Check current shared memory usage
docker exec dicloak-runtime df -h /dev/shm

Unable to Connect to the Browser via CDP

Symptom: Playwright or Puppeteer throws a connection timeout or connection refused error.

Checklist:

  • Confirm you have called /v1/env/{env_id}/open and successfully received a debug_port
  • Confirm the debug_port falls within the -p mapped range (45000–45099)
  • Confirm you requested /json/version to get the full webSocketDebuggerUrl rather than constructing the address manually
  • If connecting from another machine, confirm the bind address is 0.0.0.0, not 127.0.0.1
  • Check container logs for errors

Performance Issues / Slow Operation

Performance degrades when the number of concurrent instances exceeds hardware capacity. Recommendations:

  • Add approximately 2 GB of memory for every 10 additional concurrent instances
  • Maintain a CPU-to-instance ratio of at least 1:5
  • Mount the volume on an SSD to improve profile read/write speed

Related Links

ResourceURL
Docker Hub Image Pagehttps://hub.docker.com/r/dicloakinc/dicloak-runtime-image
DICloak Local API Developer Guidehttps://help.dicloak.com/api-development-guide/
DICloak Official Websitehttps://dicloak.com