Skip to main content
kRouter
All posts
Fix an error

Cursor ignores your localhost base URL: why, and the fix

Cursor calls a custom base URL from its own servers, so localhost never answers. How to expose a local router or Ollama safely, and the tunnel's limits.

Kodelyth · The team behind kRouter
· Updated
9 min read

You have a model on your own machine -- Ollama on port 11434, or a local router like kRouter on 20128. In Cursor's model settings you turn on Override OpenAI Base URL, paste http://localhost:20128/v1, add a custom model and send a message. Cursor shows an error that says nothing about the network.

Now look at your server's log. Nothing arrived. Not a 401, not a malformed request -- no request at all. And curl from your own terminal to the same URL answers instantly.

Your server is fine. Cursor never tried to reach it, and no setting inside Cursor will change that.

Where Cursor's request actually comes from

Cursor does not call your base URL from the editor. Its API key documentation says your key is sent to Cursor's backend with every request, because all requests are routed through Cursor's servers for final prompt building. The call to your custom endpoint is made from there.

So localhost is resolved on Cursor's server, where it means Cursor's server. The same goes for 127.0.0.1, a 192.168.x.x LAN address and host.docker.internal: private addresses do not route back to your laptop from the internet. The base URL has to be one Cursor's servers can reach publicly, which in practice means an HTTPS address.

Two more things to know first:

  • Your prompts pass through Cursor either way. The same page says Cursor's Zero Data Retention policy does not apply when you use your own keys. A local model does not make Cursor local.
  • Only chat and agent requests use your endpoint. In Cursor's words, "Custom API keys only work with chat models." Tab completion keeps using Cursor's built-in models whatever you configure.

What does not work

Binding your server to 0.0.0.0. That opens it to your local network, not to Cursor's servers. kRouter already binds to 0.0.0.0 by default, and it changes nothing here. If a tunnel is your only way in, start kRouter with --host 127.0.0.1 instead: kRouter's tunnel connects over loopback, so it keeps working and your LAN stops seeing the port.

Tunneling Ollama straight to the internet. That publishes an open model server. Ollama's documentation says the local API at localhost:11434 does not require authentication, and the maintainers have pointed people to a proxy rather than adding it; LeakIX counted 12,269 exposed instances in February 2026. Whatever you expose needs a key check in front of it.

The fix: a public HTTPS address with a key in front

You need an address Cursor's servers can reach, with a key check in front of the model. The quickest is the tunnel built into kRouter, which needs no account. Use it to prove the chain works, then decide whether to keep it; the alternatives come after.

Setting up kRouter's tunnel

Install and start kRouter, then open http://localhost:20128/dashboard:

npm install -g @sifxprime/krouter
krouter -t
  1. Set a real dashboard password. Sidebar item Settings, section Security. The tunnel will not start while the default password is in place or login is turned off.
  2. Turn on Require API key. It is in the API Keys card on the Endpoint page, and the dashboard will not start the tunnel until it is on. While you are there, click Create Key and make a key just for Cursor.
  3. Start the tunnel. In the API Endpoint card on the same page, the Tunnel row has an Enable button, then Start Tunnel. The first run downloads cloudflared. It needs outbound port 7844 (TCP and UDP), so a strict office firewall can block it, and the dashboard says to expect 10 to 30 seconds.
  4. Copy the address. The Tunnel row now shows a URL ending in /v1. The Cursor card under CLI Tools shows the same base URL next to a key picker and a model picker.

Then in Cursor, under Settings → Models:

  1. Paste the kRouter key into OpenAI API Key and make sure its toggle is on. Pasting the key and turning on the toggle are separate steps.
  2. Turn on Override OpenAI Base URL and paste the tunnel address.
  3. Add a custom model and select it in chat.

For the model name, use a kRouter combo with a plain name such as cursor-main. Direct names like cc/claude-sonnet-4-6 work too, but a neutral combo name lets you change the model behind it without touching Cursor. It also stays clear of the payload bug in the last section, which Cursor staff described by model family: GPT-5, o3, o4, gpt-4.

Local models through the same path

For Ollama, connect the Ollama Local provider in kRouter. It talks to http://localhost:11434 by default, and its models are named ollama-local/<model>. Cursor's request goes through the tunnel and kRouter's key check before it reaches Ollama, which stays on localhost. Other OpenAI-compatible servers on your machine can be added as custom providers. To keep Ollama first with a cloud model behind it, see running Ollama with a cloud fallback.

Check it with curl before you open Cursor

Cursor's errors are vague, so prove the public path first, from any machine:

KROUTER_URL="https://<your-tunnel-address>/v1"   # copied from the Endpoint page
KROUTER_KEY="<your-krouter-key>"
 
# 1. No key: expect 401
curl -s -o /dev/null -w "%{http_code}\n" "$KROUTER_URL/models"
 
# 2. With the key: expect a JSON list of model ids
curl -s "$KROUTER_URL/models" -H "Authorization: Bearer $KROUTER_KEY"
 
# 3. One real reply, not streamed
curl -s "$KROUTER_URL/chat/completions" \
  -H "Authorization: Bearer $KROUTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"<model-id>","messages":[{"role":"user","content":"Reply with OK"}],"stream":false}'

The first call matters as much as the third. A request through the tunnel counts as remote, and kRouter rejects remote callers without a key ("API key required for remote API access"). If the first call returns 200, stop and find out why before you hand the URL to anything. The same three checks work against a Tailscale or own-domain address.

If all three pass and Cursor still fails, the problem is on Cursor's side; see the last section.

What the quick tunnel is, and what it is not

kRouter's tunnel is a Cloudflare quick tunnel, the same mechanism as cloudflared tunnel --url. Cloudflare's quick tunnel documentation is blunt about it: no uptime guarantee, at most 200 requests in flight (a 429 beyond that), a new hostname every time it starts, no support for Server-Sent Events, and "for testing and development."

kRouter hides the changing hostname: the Endpoint page shows an address of the form https://r<id>.abc-tunnel.us/v1, a relay that kRouter re-registers whenever the quick tunnel restarts, so the URL in Cursor stays valid. That relay is one more hop your traffic passes through. The other limits still apply. Streamed replies are Server-Sent Events, so if replies stall or cut off partway, suspect the tunnel first. And it exists only while your machine is awake and kRouter is running.

For daily use there are two better options:

  • Tailscale Funnel. The Tailscale row on the same Endpoint page sets it up and gives you a fixed https://<device>.<tailnet>.ts.net address. Tailscale's Funnel documentation says its relays do not decrypt the traffic; Funnel must be allowed in your tailnet policy, and its bandwidth limits are not configurable. The dashboard does not insist on Require API key here, so turn it on yourself.
  • Your own server. Run kRouter on a VPS or always-on machine behind Nginx or Caddy on your own domain. Turn off response buffering so replies stream, pass X-Forwarded-For so kRouter treats every request as remote, and keep Require API key on. The deployment docs have a working Nginx block.

Which one to use

Your situationUseWhy
Trying it out, or occasional usekRouter's built-in TunnelA few clicks, no account; Cloudflare calls it a testing tool
Daily use from one machineTailscale FunnelFixed address; relays do not decrypt traffic
A team, or kRouter already on a serverYour own domain and reverse proxyStable, no relay, you control timeouts and buffering
Local models with nothing leaving your machineAn editor that runs locally, such as ClineCursor's servers are always in the path
Your own model for Tab completionNothing, todayCursor keeps Tab on its own models

When the router answers but Cursor still fails

If the curl checks pass, these are the Cursor-side problems that look like router problems. All of them come from Cursor staff replies on the Cursor forum.

"Model name is not valid." In August 2026 staff said this means the request reached Cursor without your key attached. Their first check was the OpenAI API Key toggle: a saved key does nothing while it is off. AWS Bedrock turned on in Cursor, or a team admin not enabling bring-your-own-key, has the same effect.

Cursor's own models break once the override is on. In September 2026 staff said the OpenAI key and the override apply to every model that is not a Claude or Gemini model, including Composer and Grok, and that keeping both working at once "is not available today". Turn the OpenAI key off when you switch to one of those.

Agent requests fail with "Missing required parameter". In April 2026 staff confirmed that, with the override on, GPT-5, o3, o4 and gpt-4 models were sent a Responses API body on the Chat Completions path ("Missing required parameter: 'messages'"). In late June staff said it should be fully resolved, but in August they were still tracking agent failures on the tools payload ("Missing required parameter: 'tools[6].custom'"). Update Cursor first. Staff's own workaround is a model that does not take the Responses path; confirm with one request before relying on it.

TLS or connection errors. Staff have suggested Settings → Network → HTTP Compatibility Mode set to HTTP/1.1, and Ask mode over Agent mode, which is more likely to send a plain Chat Completions request.

Common questions

Why does Cursor need a public URL when the model is on my machine?

Because Cursor's servers, not the editor, call your base URL. Cursor builds the final prompt on its backend and sends the request from there, so localhost means Cursor's own server.

Do I need a paid Cursor plan?

kRouter's Cursor guide warns that Cursor Pro is required. Cursor's own documentation describes bring-your-own-key billing for Pro, Pro+, Ultra, Teams and Enterprise, and does not mention the free Hobby plan.

Is the built-in tunnel safe to leave running?

It is locked down, but not meant to be permanent. Remote callers need a valid key, the dashboard will not start the tunnel without a custom password and Require API key, and the Cursor key can be deactivated or deleted on the Endpoint page at any time. If you only need the API, turn off Allow dashboard access via tunnel on the same page.

Which key goes in Cursor's OpenAI API Key field?

A kRouter key made just for Cursor, not one of your provider keys. Cursor sends the key it holds to its backend with every request, and a dedicated kRouter key can be cut off without touching your Anthropic, OpenAI or other accounts.

Can I use Ollama with Cursor this way?

Yes, for chat and agent requests. Connect the Ollama Local provider in kRouter, expose kRouter rather than Ollama, and add ollama-local/<model>, or a combo that points at it, as a custom model in Cursor. Tab completion still uses Cursor's own models.

Kodelyth · The team behind kRouter

Published by Kodelyth, the team that builds kRouter. Posts are drafted with AI assistance and reviewed by a person before they go out. kRouter is free and MIT licensed.

Install kRouter