9Login API: troubleshooting#
Common errors when calling the 9Login API or connecting an AI client, and how to fix them.
Connection refused: the API is off, 9Login is closed, or the port changed. The address and port are at the top of the API & MCP screen.
401 badKey: send Authorization: Bearer <key>. Only the WebSocket takes ?key= in the URL.
Use 127.0.0.1, not localhost, in tools: the API listens on IPv4 only, and some tools try IPv6 first for localhost. 403 badHost: Local only is on; call the API on 127.0.0.1, or turn Local only off on the API screen. From another machine, forward the port to 127.0.0.1 on the 9Login computer (for example with netsh interface portproxy on Windows) and keep Local only off.
Empty reply or connection reset: send HTTP/1.1 and give the body a Content-Length header. HTTP/1.0, chunked bodies and bodies over 4 MB are closed without an answer. Libraries set Content-Length for a string or bytes body; a stream or generator body is sent chunked.
403 with the plain text "origin rejected": the request carried an Origin header, as calls from a web page or browser extension do. Call the API from a script or tool.
The port is in use or reserved: pick another port on the API & MCP screen. On Windows, Hyper-V and WSL reserve port ranges; list them with: netsh interface ipv4 show excludedportrange protocol=tcp
403 toolsetOff: turn on the switch the message names on the API & MCP screen (Allow changes, Allow deleting or Allow automation). 403 planRequired: the plan has lapsed or lacks the feature. 403 notSignedIn: sign in to 9Login.
409 conflict: the proxy list or a script changed on another machine first. For a script, get it again and retry, or pass overwrite true; for the proxy list, onConflict "reload" takes that version and applies the change on top.
Extension install and delete answer 200 and report a catalogue conflict (or notSynced or rejected) in catalogue.status: this computer has the change but the account does not.
An AI client misses a tool: Allow changes, Allow deleting or Allow automation is off, the sub-user lacks the permission, the plan lacks scripts (automation), or the client kept an old list; reconnect it. The window tools exist on Windows only.
409 notRunning on an automation call: start the profile first. A profile already running since before this version of 9Login (or since a Sync control session) has no automation: stop it and start it again. 409 inSync: the profile is in a Sync control session, which is driven by hand.
422 macroError: the macro threw, lost its tab or ran past timeoutSec; message has the error and details.logs what it logged. A run past timeoutSec may still be going on in the browser; GET /v1/profiles/{id}/logs shows what it prints after that.
A profile whose proxy is a script entry does not open: its row shows the error of the script. Run the entry with POST /v1/proxies/test-script (pass id, and profileId for that profile) to see what it logged and why it failed; GET /v1/proxies/script-docs lists the errors and their fixes.
A profile's script did not run, or ran on an old page: the profile has onStartup "restore", which reopens the last session before the script starts. Set onStartup to "custom" with a url when the run depends on the script. GET /v1/profiles/{id}/logs has what the script printed, also after the browser closed.
A task did not fire: 9Login must be open and signed in at that time, and the task must be on (enabled). A firing missed while 9Login was closed is skipped, not run late. GET /v1/tasks/{id} shows state.nextRunAt. A profile already open runs the script in its open browser; one the task skipped says why in GET /v1/task-runs/{id}: busy (another script or automation call was running in it), profileRunning (it was opening or closing at that moment), lockedElsewhere (another computer of the account opened it first), inSync, noChannel, dataBusy, noScript.
A task's browsers stay open, or pile up over time: a task never closes a browser. When the script finishes, the browser stays open as the script left it, and the next firing runs the script again in that open browser. End the script with Exit() to close the browser when its work is done, or set the profile's Duration (seconds) so it closes by itself. Stopping a run closes every browser it is running the script in, also ones that were open before the run.
Making a new key stops every tool or AI client that uses the old one until it gets the new one.