# DouBao2Api A Dockerized solution that converts the web version of Doubao (doubao.com) into an OpenAI-compatible API. It uses VNC + Playwright to simulate real human browser interaction — sending messages indirectly and capturing replies — while exposing a standard `/v1/chat/completions` endpoint.

[**中文**](README.md) | [English](README_EN.md)
## How It Works ``` ┌──────────────────────────────────────────────────────────┐ │ Docker Container (RockyLinux 9) │ │ │ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │ │ Xvfb │──│ openbox │──│ Chromium │──│Playwright│ │ │ │ Virtual │ │ Window Mgr │ │ Browser │ │ Automation│ │ │ │ Display │ └──────────┘ └──────────┘ └────────┘ │ │ └─────────┘ │ │ │ │ ┌──────────┐ │ │ │ └──────────│ x11vnc │◄───────────────────────┘ │ │ │ VNC Server│ │ │ └────┬─────┘ │ │ │ │ │ ┌────┴─────┐ ┌──────────┐ │ │ │websockify│──│ noVNC │ │ │ │ Proxy │ │ Web Client│ │ │ └──────────┘ └──────────┘ │ │ │ │ ┌──────────────────────┐ │ │ │ FastAPI (port 8000) │ │ │ │ OpenAI-compatible API │ │ │ └──────────────────────┘ │ └──────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ API :8000 VNC :5900 noVNC :6080 ``` **Core flow**: API receives request → Playwright operates the Doubao page in Chromium (type message, press Enter) → DOM polling captures streaming reply → returned as SSE or JSON. ## Features - **OpenAI-compatible**: Standard `/v1/chat/completions` endpoint with both streaming (SSE) and non-streaming responses - **VNC visualization**: Real-time browser view via noVNC web client, with view-only/interactive toggle - **Anti-detection**: Playwright stealth script hides webdriver flags, simulates human typing delays - **Session persistence**: Login state saved via `storage_state` to a Docker volume — no re-login after restart - **Chat reuse**: Reuses the current chat session by default to reduce risk control triggers; supports on-demand new chat creation - **Debug endpoint**: `/inspect` returns page DOM structure for easy selector adaptation ## Quick Start ### 1. Build & Start ```bash docker compose build docker compose up -d ``` ### 2. Login to Doubao After the container starts, open noVNC in your browser: ``` http://localhost:6080/vnc.html ``` VNC password: `doubao123` (configurable via `VNC_PASSWORD` in `docker-compose.yml`) noVNC defaults to **view-only mode** (to prevent accidental interaction). Uncheck "View Only" in the left sidebar settings to switch to interactive mode. Log in to your Doubao account in the Chromium browser within VNC. Make sure you can see the chat input box. ### 3. Save Login State ```bash curl -X POST http://localhost:8000/login/save ``` ### 4. Call the API ```bash # Non-streaming curl http://localhost:8000/v1/chat/completions \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"model":"doubao-pro","messages":[{"role":"user","content":"Hello"}]}' # Streaming curl http://localhost:8000/v1/chat/completions \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"model":"doubao-pro","messages":[{"role":"user","content":"Hello"}],"stream":true}' ``` ## Configuration All settings are configured via environment variables in `docker-compose.yml` or `.env`: | Variable | Default | Description | |----------|---------|-------------| | `API_KEY` | `sk-your-api-key-here` | API authentication key; clients must send `Authorization: Bearer ` header | | `API_PORT` | `8000` | API service port | | `VNC_PASSWORD` | `doubao123` | VNC connection password | | `VNC_VIEW_ONLY` | `false` | Force x11vnc server-side view-only (`true` blocks all input even if noVNC unchecks View Only) | | `VNC_PORT` | `5900` | Direct VNC port | | `NOVNC_PORT` | `6080` | noVNC web client port | | `DOUBAO_URL` | `https://www.doubao.com/chat/` | Doubao chat page URL | | `BROWSER_HEADLESS` | `false` | Run browser in headless mode (must be `false` for VNC) | | `RESPONSE_TIMEOUT` | `120` | Response timeout in seconds | | `TYPING_DELAY_MIN` | `30` | Minimum typing delay (ms per character) | | `TYPING_DELAY_MAX` | `80` | Maximum typing delay (ms per character) | | `INTER_MESSAGE_DELAY` | `0.5` | Delay before sending message (seconds) | | `SCREEN_WIDTH` | `1280` | Virtual screen width | | `SCREEN_HEIGHT` | `720` | Virtual screen height | | `SCREEN_DEPTH` | `24` | Virtual screen color depth | | `LOG_LEVEL` | `INFO` | Log level | ## API Reference ### `POST /v1/chat/completions` OpenAI-compatible chat endpoint. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `model` | string | `doubao-pro` | Model name | | `messages` | array | required | Message array, same format as OpenAI | | `stream` | bool | `false` | Enable SSE streaming response | | `new_chat` | bool | `false` | Start a new chat session (custom extension field) | ### `GET /v1/models` Returns the list of supported models. ### `GET /login/status` Check current Doubao login status. ### `POST /login/save` Persist current browser state (cookies, storage) to disk. ### `POST /chat/new` Explicitly start a new Doubao chat session. ### `GET /inspect` Return current page DOM structure for debugging selectors. ### `GET /vnc/mode` Get current VNC mode (`viewonly` or `interactive`). ### `POST /vnc/mode` Switch VNC mode (server-side enforcement): ```bash # Switch to interactive mode curl -X POST http://localhost:8000/vnc/mode \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"mode":"interactive"}' # Switch to view-only mode curl -X POST http://localhost:8000/vnc/mode \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"mode":"viewonly"}' ``` ### `POST /browser/restart` Restart the browser session. ### `GET /health` Health check endpoint. ## VNC Modes Two layers of view-only control: | Layer | Control | Default | Description | |-------|---------|---------|-------------| | Client | noVNC sidebar "View Only" checkbox | Checked (read-only) | Uncheck to switch to interactive instantly; refresh restores read-only | | Server | API `POST /vnc/mode` | `interactive` | `viewonly` mode makes x11vnc reject all input, even if the client unchecks View Only | For daily use, the client layer is sufficient. For stronger enforcement (prevent any VNC client from interacting), use the API to switch the server-side mode. ## Project Structure ``` DouBao2Api/ ├── Dockerfile # Docker image build file ├── docker-compose.yml # Container orchestration ├── requirements.txt # Python dependencies ├── .env.example # Environment variable template ├── app/ │ ├── __init__.py │ ├── config.py # Configuration management (pydantic-settings) │ ├── models.py # OpenAI-compatible data models │ ├── browser_manager.py # Playwright browser management │ ├── doubao.py # Doubao page interaction logic │ └── main.py # FastAPI service entry point └── scripts/ ├── entrypoint.sh # Container entrypoint script ├── supervisord.conf # Process management config ├── start_wm.sh # Window manager startup script └── start_x11vnc.sh # x11vnc startup script (view-only/interactive toggle) ``` ## Process Architecture Five processes managed by supervisord inside the container, started by priority: | Priority | Process | Description | |----------|---------|-------------| | 10 | Xvfb | Virtual framebuffer X server | | 20 | openbox | Lightweight window manager | | 30 | x11vnc | VNC server, maps Xvfb display | | 40 | websockify | WebSocket proxy, provides noVNC web access | | 50 | uvicorn | FastAPI application server | ## Troubleshooting ### Build failure: package not found This project is based on RockyLinux 9. RHEL 10 / RockyLinux 10 removed X11 server packages and does not support this approach. Docker containers are independent of the host OS — running an RL9 container on an RL10 host is fully compatible. ### API returns empty response Doubao frontend updates may break CSS selectors. Call `GET /inspect` to view the current DOM structure, then update the selector constants in `app/doubao.py`. ### "Not logged in" error You must first log in to Doubao through the VNC browser, then call `POST /login/save` to persist the state. Use `GET /login/status` to check login status. ### VNC cannot interact Make sure "View Only" is unchecked in the noVNC sidebar. If still unable to interact, check server-side mode: `GET /vnc/mode`. If it returns `viewonly`, use the API to switch to `interactive`. ## Tech Stack - **RockyLinux 9** — Container base OS - **Xvfb + x11vnc + noVNC** — Virtual display and remote viewing - **Playwright** — Browser automation - **FastAPI + Uvicorn** — API service - **Supervisor** — Process management - **websockify** — VNC over WebSocket proxy ## Disclaimer This project is for educational and research purposes only. Please ensure compliance with Doubao's terms of service before use. The author is not responsible for any direct or indirect consequences arising from the use of this project.