TurnAPI converts a chat interface running inside Chromium into an API.
The primary goal is not the localhost UI. The primary goal is:
- attach to a real browser session
- drive a website chat surface
- wait until the remote answer is fully generated
- expose that interaction through stable HTTP endpoints
The localhost UI is optional and sits on top of the same backend.
The codebase currently works as a browser-backed API bridge with:
- session creation
- multi-turn session reuse
- parallel sessions
- stored remote conversation links via
session_link - minimal OpenAI-style and Anthropic-style endpoints
The current live-tested targets are:
consensus.appchat.z.ai
The runtime is structured so target-specific logic can be swapped through adapters and selector overrides.
Recommended for real use:
- run a long-lived Chromium-based browser
- keep it headful but hidden/background instead of true headless
- attach the API to that browser over CDP
This is the most stable model for authenticated sites and sites with anti-bot pressure.
If you want to use your real local logged-in profile on macOS:
BROWSER_CHAT_BROWSER_APP="Brave Browser" \
BROWSER_CHAT_WINDOW_MODE=background \
BROWSER_CHAT_CDP_PORT=9444 \
uv run python run.py chrome-localIf you want a dedicated automation profile:
BROWSER_CHAT_BROWSER_APP="Brave Browser" \
BROWSER_CHAT_WINDOW_MODE=background \
BROWSER_CHAT_CDP_PORT=9444 \
uv run python run.py chromeBROWSER_CHAT_MODE=attach \
BROWSER_CHAT_CDP_URL=http://127.0.0.1:9444 \
uv run python run.pycurl -s http://127.0.0.1:8002/health- Swagger UI:
http://127.0.0.1:8002/docs - Local UI:
http://127.0.0.1:8002/
Create a new remote session and send the first prompt:
curl -s -X POST http://127.0.0.1:8002/chat/sync \
-H 'Content-Type: application/json' \
-d '{
"message": "What are the effects of caffeine on sleep?"
}'Example against chat.z.ai:
curl -s -X POST http://127.0.0.1:8002/chat/sync \
-H 'Content-Type: application/json' \
-d '{
"message": "Reply with exactly two words: QUIET HARBOR.",
"target_url": "https://chat.z.ai/"
}'Continue the same session:
curl -s -X POST http://127.0.0.1:8002/chat/sync \
-H 'Content-Type: application/json' \
-d '{
"message": "Focus only on adolescents",
"session_id": "abc12345"
}'Resume from a stored remote conversation URL:
curl -s -X POST http://127.0.0.1:8002/chat/sync \
-H 'Content-Type: application/json' \
-d '{
"message": "Continue this conversation",
"session_link": "https://consensus.app/search/..."
}'Example against a stored chat.z.ai conversation:
curl -s -X POST http://127.0.0.1:8002/chat/sync \
-H 'Content-Type: application/json' \
-d '{
"message": "Now answer with exactly one word: FOAM.",
"session_link": "https://chat.z.ai/c/..."
}'curl -s -X POST http://127.0.0.1:8002/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "browser-chat",
"messages": [
{"role": "user", "content": "What are the effects of caffeine on sleep?"}
]
}'Streaming:
curl -N -X POST http://127.0.0.1:8002/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "browser-chat",
"stream": true,
"messages": [
{"role": "user", "content": "What are the effects of caffeine on sleep?"}
]
}'curl -s -X POST http://127.0.0.1:8002/v1/messages \
-H 'Content-Type: application/json' \
-d '{
"model": "browser-chat",
"messages": [
{"role": "user", "content": "What are the effects of caffeine on sleep?"}
]
}'Create/open a session without sending a real prompt yet:
curl -s -X POST http://127.0.0.1:8002/v1/sessions \
-H 'Content-Type: application/json' \
-d '{
"target_url": "https://consensus.app/search/"
}'List active in-memory sessions:
curl -s http://127.0.0.1:8002/v1/sessionsInspect one session:
curl -s http://127.0.0.1:8002/v1/sessions/abc12345- No
session_id: create a new managed tab. session_id: continue the same active managed tab.session_link: reopen the remote conversation URL in a managed tab and continue from there.- Multiple sessions can run in parallel up to the configured session limit.
BROWSER_CHAT_MODE
attachpersistentephemeral
Recommended: attach
BROWSER_CHAT_CDP_URL
- Example:
http://127.0.0.1:9444
BROWSER_CHAT_PROFILE_DIR
- Used by
persistent
BROWSER_CHAT_WINDOW_MODE
backgroundoffscreenvisibleminimized
Recommended: background
BROWSER_CHAT_BROWSER_APP
Brave BrowserGoogle Chrome
BROWSER_CHAT_CHROME_USER_DATA_DIR
- Chromium user-data root
BROWSER_CHAT_CHROME_PROFILE_DIRECTORY
DefaultProfile 1Profile 2
BROWSER_CHAT_CDP_PORT
- Example:
9444
BROWSER_CHAT_URL
- default target URL
BROWSER_CHAT_INPUT_SELECTORS
- comma-separated selectors for the chat box
BROWSER_CHAT_SUBMIT_SELECTORS
- comma-separated selectors for the send button
BROWSER_CHAT_RESPONSE_SELECTORS
- comma-separated selectors for answer extraction
BROWSER_CHAT_SOURCE_SELECTORS
- comma-separated selectors for source extraction
BROWSER_CHAT_WAIT_TIMEOUT_SECONDS
- maximum wait for a finished answer
BROWSER_CHAT_POLL_INTERVAL_SECONDS
- how frequently the page is scraped
BROWSER_CHAT_STABLE_POLLS
- how many unchanged polls are required before treating the answer as complete
The project purpose is Linux Chromium automation. The core runtime is already Chromium/CDP-based, but the helper launcher in run.py is still most polished for macOS local-profile launching. On Linux, the recommended pattern is still the same:
- launch Chromium/Chrome manually with remote debugging
- point
BROWSER_CHAT_CDP_URLat it - run TurnAPI in
attachmode
- Sites with auth walls still require a valid logged-in browser session.
- True headless mode is less reliable than hidden/background headful mode.
- Selector tuning is still target-specific.
- Session state is in memory; restarting the API drops
session_idmappings, thoughsession_linkcan be reused later. - Source extraction is generic and may need target-specific improvement.
- Anti-bot protections can still block or degrade automation depending on the site.
- Real app URL:
https://chat.z.ai/ - Input:
textarea - Send button:
#send-message-button - Conversation URLs:
https://chat.z.ai/c/<uuid> - The
thinking-chain-containercontains intermediate reasoning/loading content and must be excluded from final answer extraction. - Attach mode works best when reusing an already-open matching conversation tab for
session_linkresume.
- Core target abstraction: consensus_api.py
- Browser session management: consensus_api.py
- API endpoints: consensus_api.py
- Launcher helper: run.py
- Tests: test_consensus_api.py
- Project operating docs: project.md, agent.md, techniques.md, tasks.md