SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

The Ollama API and port 11434 explained

Curl your Ollama server on port 11434, read what a refused connection means, tour the API endpoints, and set OLLAMA_HOST without exposing the box.

What port 11434 is for

The Ollama API listens on TCP (transmission control protocol) port 11434, and one curl to /api/tags tells you whether it is answering. Run it on the server itself before you try anything from another machine.

curl http://localhost:11434/api/tags

Two outcomes matter. Either JSON comes back, which means the server process is up and the API is answering on that port. Or curl prints Connection refused, which means nothing is listening on that address. A refusal happens below the application: the TCP layer is reporting that no process holds the port, so authentication and model names are not involved yet.

/api/tags is the right first request because it needs no body and loads no model. It lists what you have already pulled.

The response is a JSON object with a models array. Below is the shape, trimmed for readability. Treat it as an illustration rather than a promise: your own model names and sizes will differ, and fields get added between releases.

{
  "models": [
    {
      "name": "llama3.2:latest",
      "model": "llama3.2:latest",
      "size": 2019393189,
      "details": {
        "format": "gguf",
        "family": "llama",
        "parameter_size": "3.2B",
        "quantization_level": "Q4_K_M"
      }
    }
  ]
}

An empty models array is a healthy server with nothing pulled yet. That is a different problem from a refused connection, and the fix is a pull, not a restart.

Why curl says Connection refused

Work through four checks in order. Each one rules out a different cause.

  1. systemctl status ollama tells you whether the service is running at all. A unit sitting in inactive (dead) explains the refusal on its own.
  2. ss -ltnp | grep 11434 shows which address the listener is bound to. Nothing printed means nothing is listening.
  3. journalctl -e -u ollama shows why the server stopped, or why it failed to start.
  4. curl http://localhost:11434/api/version asks for the server version. It is the smallest request that proves the API itself is answering.

The most common cause is not a crash. Ollama binds 127.0.0.1 port 11434 by default, so it accepts connections from the server itself and from nowhere else. A curl from your laptop to http://your-vps-ip:11434/api/tags is refused because the listener is not on that address, even while the same request works fine over SSH on the box. The fix is OLLAMA_HOST, covered further down, and it deserves a moment of thought before you use it.

The endpoints that matter on a server

The native API lives under /api on that one port. These are the paths worth knowing when Ollama runs on a VPS rather than a laptop.

  • GET /api/tags lists the models on disk.
  • POST /api/pull downloads a model by name.
  • POST /api/generate runs a single prompt through a model.
  • POST /api/chat runs a message list through a model.
  • POST /api/embed turns text into vectors.
  • GET /api/ps lists the models currently loaded in memory.
  • POST /api/show returns a model's template and its parameters.
  • DELETE /api/delete removes a model from disk.
  • GET /api/version returns the server version.

generate versus chat: which one to call

/api/generate takes a prompt string. It applies the model's template and returns one completion. There is no conversation state on the server, so a follow-up question needs the whole history sent again.

/api/chat takes a messages array, where each entry carries a role of system, user, assistant or tool, plus its content. This is the endpoint that supports tool calling. Ollama keeps no memory of previous turns here either: your client sends the full array every time.

Use /api/chat for anything conversational and for anything that calls tools. Use /api/generate for one-shot text work such as classification or summarising, where a message array adds nothing.

curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "Why is the sky blue?",
  "stream": false
}'
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [
    {
      "role": "user",
      "content": "why is the sky blue?"
    }
  ],
  "stream": false
}'

Swap llama3.2 for a model you have actually pulled. Asking for a model that is not on disk returns 404. The API does not download it for you.

Streaming is the default, and it surprises people

/api/generate and /api/chat stream by default, and so does /api/pull. A streaming response is NDJSON (newline-delimited JSON): one JSON object per line, not one JSON document. Hand that whole body to a JSON parser and the parse fails, because the body was never a single object.

Set "stream": false and you get one object instead, once the model has finished. That is the easier shape for a script. The cost is latency: nothing arrives until the last token is generated.

In a streaming response the final line carries "done": true along with timing fields such as total_duration and eval_count. The durations are in nanoseconds, so eval_duration of 4709213000 is about 4.7 seconds. Dividing eval_count by that number of seconds is the honest way to measure tokens per second on a local model, because the figure comes from the request you actually ran.

Pulling a model over the API

curl http://localhost:11434/api/pull -d '{"model": "llama3.2"}'

The connection stays open for the length of the download, and progress objects arrive as they happen. Add "stream": false to wait quietly and receive a single status object at the end. A pull over the API writes to the same model store the command line uses, so ollama list on the box shows the model afterwards.

This matters on a fresh server, where the first thing you want after the install is a model on disk. If you are setting the machine up now, start from a working Ollama install on a VPS and come back to the API once ollama list shows something.

Embeddings

curl http://localhost:11434/api/embed -d '{
  "model": "all-minilm",
  "input": "Why is the sky blue?"
}'

input accepts a string or an array of strings, so a batch goes in one request. The response carries an embeddings field holding one vector per input, plus timing fields.

An older /api/embeddings endpoint still answers. It takes prompt instead of input, and it returns a single embedding rather than an embeddings array. New code should use /api/embed. The differing field names are the usual reason a copied example returns vectors your code reads as undefined.

The OpenAI-compatible path at /v1

Ollama also serves an OpenAI-compatible API on the same port, under /v1. Point an existing client at http://localhost:11434/v1 and it works with no code changes.

curl -X POST http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
  "model": "gpt-oss:20b",
  "messages": [{ "role": "user", "content": "Say this is a test" }]
}'

The compatible surface covers /v1/chat/completions, /v1/completions, /v1/models, /v1/models/{model}, /v1/embeddings and /v1/responses. Most SDKs (software development kits) need two settings: a base URL of http://localhost:11434/v1, and an API key. Ollama ignores the key, but many clients refuse to start without one, so set it to the string ollama.

As of August 2026 the compatibility layer does not implement everything. Logprobs are unsupported. Images must be sent as base64 rather than as a URL. tool_choice is not honoured, and stateful requests to /v1/responses are not supported. Test the feature you depend on before you trust it through this path. This is the route most editor plugins take, and it is how you point a coding agent at your own Ollama server instead of a paid endpoint.

What OLLAMA_HOST does

OLLAMA_HOST sets the address and the port the Ollama server binds. The default is 127.0.0.1:11434, which is loopback only.

The same variable does a second job on the client side. OLLAMA_HOST=http://10.0.0.5:11434 ollama list asks a remote server what it holds. One name, two meanings: on the server process it decides where to listen, and on the command line it decides where to connect. Confusing the two is why people export the variable in their shell, restart nothing, and then see no change in the bind address.

On Linux the server runs under systemd as the ollama user, so a variable exported in your interactive shell never reaches it. Edit the unit instead.

sudo systemctl edit ollama.service

Add this block in the editor that opens.

[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"

Then reload and restart, and look at the listener again.

sudo systemctl daemon-reload
sudo systemctl restart ollama
ss -ltnp | grep 11434

ss should now show the listener on 0.0.0.0:11434 rather than 127.0.0.1:11434. If it still shows loopback, the override did not apply: run systemctl show ollama --property=Environment to see what the service actually received, and confirm the file landed under /etc/systemd/system/ollama.service.d/.

Why exposing the Ollama API is a deliberate act

The Ollama API has no authentication. There is no token, no user and no login step. Anyone who can reach port 11434 can list your models, pull new ones, delete them, and run generation on your hardware at your expense.

0.0.0.0 means every network this machine sits on, and on a VPS that includes the public internet. Scanners find an open 11434 quickly, because it is a fixed default port. So decide who needs access before you change the bind, and put a control in front of it: a firewall rule that allows one source address, or a reverse proxy that requires a password. Those options need more room than this page has, and hardening a public Ollama endpoint covers them properly.

For a single user the safer answer is to leave the bind on loopback and tunnel over SSH.

ssh -N -L 11434:127.0.0.1:11434 user@your-server

While that command runs, curl http://localhost:11434/api/tags on your laptop reaches the server's loopback interface through the SSH session. Nothing is published to the internet, and no firewall rule is needed.

How to change the Ollama port when 11434 is taken

Ports collide. Another service, or a second copy of Ollama, may already hold 11434. Find out which process owns it before you change anything.

sudo ss -ltnp | grep 11434

When ollama serve cannot take the port it exits at once, and the message names the address and ends with bind: address already in use. The usual cause is that the systemd service is already running and you started a second server by hand. Stop one of them with sudo systemctl stop ollama, or simply use the service that is already up.

To move the port, set it inside the same variable, because OLLAMA_HOST carries the address and the port together.

[Service]
Environment="OLLAMA_HOST=127.0.0.1:11500"

After daemon-reload and restart, every client has to follow. The command line needs OLLAMA_HOST=http://127.0.0.1:11500, and any HTTP client needs its base URL changed to match. A client still pointed at 11434 gets Connection refused, which reads like a dead server but is only a stale address.

Two more variables worth knowing

OLLAMA_ORIGINS controls CORS (cross-origin resource sharing). Ollama allows browser requests from 127.0.0.1 and 0.0.0.0 by default, so a web page served from any other origin is blocked by the browser before its request reaches Ollama. Add the origins you need, for example Environment="OLLAMA_ORIGINS=chrome-extension://*". CORS is enforced by the browser, so it stops a web page and does nothing at all about curl.

OLLAMA_KEEP_ALIVE sets how long a model stays in memory after a request. The default is five minutes, after which the weights are unloaded and the next request pays the load time again. Per request you can send "keep_alive": "30m", or -1 to hold the model in memory indefinitely. GET /api/ps shows what is loaded right now, with an expires_at timestamp and the memory each model holds. The trade between memory and first-token latency is worked through in keeping an Ollama model loaded in memory.

Per-request options

Both /api/generate and /api/chat accept an options object carrying model parameters.

curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [{"role": "user", "content": "summarise this log line"}],
  "stream": false,
  "options": {"temperature": 0, "num_ctx": 8192}
}'

num_ctx is the option that changes memory use the most, because the KV cache (key-value cache) grows with the context length. Set it too high on a small VPS and the model spills out of RAM or fails to load at all. Sizing num_ctx for your hardware covers how to pick a number. If several clients will hit the API at the same time, queue behaviour matters too, and OLLAMA_NUM_PARALLEL and OLLAMA_MAX_QUEUE decide how many requests run together and how many wait.

Failure modes and the strings you will see

Connection refused. Nothing is listening on that address and port. Check the service first, then check the bind address with ss -ltnp. From a remote machine this nearly always means Ollama is still on loopback.

404 with an error field. The model name is not on disk. /api/generate does not pull on demand. Run the pull first, and check the tag as well as the name: llama3.2 and llama3.2:1b are different models.

400 with an error field. The request body was rejected. In a shell this is usually quoting. Writing -d "{"model": "llama3.2"}" collapses, because the shell removes the outer double quotes before curl ever sees them. Wrap the JSON in single quotes, or put it in a file and send -d @request.json.

429, too many requests. This comes from a rate limit. Seeing it against your own server is a sign that your base URL points at a hosted endpoint rather than at port 11434 on your box.

An error arriving in the middle of a stream. A streaming response has already sent HTTP 200 by the time the model fails, so the status code stays 200 and the failure appears as a JSON object with an error field inside the stream. A client that checks only the status code will report success on a failed generation. Parse every line.

The first request takes far longer than the rest. The model is being read from disk into memory. GET /api/ps returning an empty list before the call and a loaded model after it confirms exactly that. Raising keep_alive stops it repeating.

Every command here runs against your own instance, so the output you get is your server's, not a transcript of mine. Run them in order on the box before you touch the bind address, and you will know which layer is broken when something stops answering.

FAQ

What is port 11434 used for?

Port 11434 is the default TCP port of the Ollama HTTP API. The server binds 127.0.0.1:11434 after a standard install, and the ollama command line plus every HTTP client talk to it there. The native API sits under /api, and an OpenAI-compatible API sits under /v1 on the same port. curl http://localhost:11434/api/tags is the quickest check that it is answering.

Why does curl to port 11434 say Connection refused?

Nothing is listening on the address you asked for. Run systemctl status ollama to confirm the service is up, then ss -ltnp | grep 11434 to see the bind address. If the check works on the server but fails from your laptop, the cause is the default bind: Ollama listens on 127.0.0.1 only, so a connection arriving on the public interface is refused. Either set OLLAMA_HOST and add access control, or forward the port with ssh -N -L 11434:127.0.0.1:11434 user@your-server.

How do I expose the Ollama API to another machine?

Run sudo systemctl edit ollama.service and add Environment="OLLAMA_HOST=0.0.0.0:11434" under a [Service] line, then run sudo systemctl daemon-reload and sudo systemctl restart ollama. Confirm the new bind with ss -ltnp | grep 11434. Editing the unit is required because the server runs as the ollama user under systemd, so a variable exported in your shell never reaches it. The API has no authentication of any kind, so put a firewall rule or a password-protected proxy in front before the port is reachable from the internet.

How do I change the Ollama port?

Set the port inside OLLAMA_HOST, since that variable carries both the address and the port. Put Environment="OLLAMA_HOST=127.0.0.1:11500" in the systemd override, then reload and restart. Update every client too, because one still pointed at 11434 gets a connection refusal that looks like a dead server. If ollama serve exited with bind: address already in use, run sudo ss -ltnp | grep 11434 first: the port is often held by an Ollama service that is already running.

What is the difference between /api/generate and /api/chat?

/api/generate takes a single prompt string and returns one completion. /api/chat takes a messages array with a role on each entry, and it is the endpoint that supports tool calling. Neither keeps conversation state on the server, so your client sends the full history on every turn. Use /api/chat for anything conversational, and /api/generate for one-shot text work such as classification.