How to Call the Ollama API With Examples You Can Run
Call the Ollama REST API on localhost:11434: generate and chat requests, streaming output, listing models, Python and JavaScript examples, and fixes.

The Ollama API is a plain HTTP REST API that the Ollama server exposes at http://localhost:11434/api when it runs on your machine. You send JSON with curl, fetch, or urllib, and you get JSON back. No SDK and no API key are needed for local requests. As of October 17, 2026, Ollama's API overview lists a second base URL, https://ollama.com/api, for cloud models, and that one does require a key.
The two endpoints you'll use most are /api/generate for a single prompt and /api/chat for a conversation built from messages. Both stream newline-delimited JSON by default and both accept "stream": false when you'd rather receive one response object. GET /api/tags lists the models you've downloaded. Below are the smallest requests that work for each, how to read the streamed output, and the same calls from Python and JavaScript.
Where the Ollama API lives: URL and port#
A local Ollama server listens on port 11434 and serves three API surfaces from the same process. The native API is the one this page covers. The other two exist so that existing OpenAI and Anthropic client code can point at Ollama without changes.
| API surface | Local Ollama server | Direct cloud access |
|---|---|---|
| Ollama native API | http://localhost:11434/api |
https://ollama.com/api |
| OpenAI compatibility | http://localhost:11434/v1 |
https://ollama.com/v1 |
| Anthropic client base URL | http://localhost:11434 |
https://ollama.com |
The Anthropic client appends /v1/messages to its base URL on its own, which is why that row has no path. Creating or deleting models only works against a local server, not the cloud endpoint.
The quickest health check is a GET on the root:
curl http://localhost:11434
If the server is up, it answers with the text Ollama is running. If curl reports a connection refused, nothing is listening yet. The troubleshooting section further down covers that case. If you haven't installed Ollama or pulled a model yet, the walkthrough on running an Ollama model locally and calling it from code gets you to that point.
Ollama API endpoints you'll actually use#
The full endpoint list, with every request and response field, is in the Ollama API reference on GitHub. These are the ones most applications touch:
| Method and path | What it does |
|---|---|
POST /api/generate |
One prompt in, one completion out |
POST /api/chat |
A messages array in, an assistant message out |
GET /api/tags |
List the models downloaded on this server |
POST /api/show |
Details about one model |
POST /api/pull |
Download a model from the library |
POST /api/embed |
Turn text into embedding vectors |
GET /api/ps |
Show which models are currently loaded in memory |
For embeddings specifically, the guide to running EmbeddingGemma 2 with Ollama covers model choice and output dimensions.
Ollama's API overview says the API isn't strictly versioned but is expected to stay stable and backwards compatible, with deprecations announced in the release notes. In practice that means code written against /api/chat keeps working across upgrades.
Generate vs chat: the smallest requests that work#
/api/generate takes a prompt string. Use it for one-shot tasks such as summarizing a paragraph or rewriting a sentence.
curl http://localhost:11434/api/generate -d '{
"model": "gemma4:31b",
"prompt": "Why is the sky blue?",
"stream": false
}'
The text comes back in the response field, and done is true because streaming is off. The model value has to match a model you've already pulled, including the tag after the colon. Swap gemma4:31b for whatever /api/tags reports on your machine.
/api/chat takes a messages array with role and content on each entry. This is the endpoint to pick for anything conversational, and it's also the one Ollama's own docs use as the canonical example:
curl http://localhost:11434/api/chat \
-H "Content-Type: application/json" \
-d '{
"model": "gemma4:31b",
"messages": [{"role": "user", "content": "Why is the sky blue?"}],
"stream": false
}'
Read the answer from message.content. The message.role will be assistant. Two things that catch people on their first multi-turn chat:
- The server keeps no conversation state. Each request stands alone, so you append the assistant's reply to your
messagesarray and send the whole history back on the next turn. - A system prompt is just another message. Put
{"role": "system", "content": "..."}first in the array.
Both endpoints accept an options object for sampling settings such as "options": {"temperature": 0}, and a "format": "json" flag when you want the model to emit valid JSON. Keep those out of your first request and add them once the plain call works.
Streaming responses and how to read them#
Leave stream out, or set it to true, and the server writes one JSON object per line as tokens arrive. Each line is complete JSON on its own. The body as a whole is not a JSON array, which is the single most common parsing mistake with this API.
curl http://localhost:11434/api/chat -d '{
"model": "gemma4:31b",
"messages": [{"role": "user", "content": "Say hello in five words."}]
}'
For /api/chat the partial text is in message.content on each line. For /api/generate it's in response. The last line has "done": true and carries the summary fields such as done_reason and eval_count. Your loop should concatenate the text pieces and stop when it sees done.
Here's that logic against a captured stream, with no server required:
import json
# Four lines exactly as /api/chat streams them: newline-delimited JSON.
stream = """{"model":"gemma4:31b","message":{"role":"assistant","content":"The sky "},"done":false}
{"model":"gemma4:31b","message":{"role":"assistant","content":"looks blue because "},"done":false}
{"model":"gemma4:31b","message":{"role":"assistant","content":"of Rayleigh scattering."},"done":false}
{"model":"gemma4:31b","message":{"role":"assistant","content":""},"done":true,"done_reason":"stop","eval_count":12}"""
parts = []
for line in stream.splitlines():
if not line.strip():
continue
chunk = json.loads(line)
parts.append(chunk["message"]["content"])
if chunk["done"]:
print("done_reason:", chunk.get("done_reason"))
print("eval_count:", chunk.get("eval_count"))
print("text:", "".join(parts))
I'd stream in anything user-facing. Waiting for a long answer with no feedback feels broken, and the parsing is a dozen lines.
Listing models with /api/tags#
GET /api/tags returns the models stored on the server. It's the fastest way to answer "what model name do I put in the request?" and it's handy as a startup check in your own code.
curl http://localhost:11434/api/tags
The response is an object with a models array. Each entry has a name (the exact string to use in model), a size in bytes, and a modified_at timestamp. This snippet shows how to turn that payload into a readable list and check that a required model is present:
// Shape of GET /api/tags, trimmed to the fields most code needs.
const tags = {
models: [
{ name: "gemma4:31b", size: 19_800_000_000, modified_at: "2026-10-12T09:14:00Z" },
{ name: "my-finetune:latest", size: 4_700_000_000, modified_at: "2026-10-15T18:02:00Z" },
],
};
const gb = (bytes) => (bytes / 1e9).toFixed(1) + " GB";
for (const m of tags.models) {
console.log(m.name.padEnd(22), gb(m.size).padStart(8), m.modified_at.slice(0, 10));
}
const names = tags.models.map((m) => m.name);
console.log("gemma4:31b available:", names.includes("gemma4:31b"));
If you request a model that isn't in this list, the server answers with a 404 and an error field saying the model was not found. Pull it first, then retry.
Calling the Ollama API from Python and JavaScript#
You don't need a library. Python's standard urllib can stream a chat response line by line:
import json
import urllib.request
req = urllib.request.Request(
"http://localhost:11434/api/chat",
data=json.dumps({
"model": "gemma4:31b",
"messages": [{"role": "user", "content": "Why is the sky blue?"}],
}).encode(),
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as resp:
for line in resp:
chunk = json.loads(line)
print(chunk["message"]["content"], end="", flush=True)
if chunk["done"]:
print()
In Node.js, fetch gives you the body as an async-iterable stream. Buffer partial lines, because a network chunk can end mid-object:
const res = await fetch("http://localhost:11434/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "gemma4:31b",
messages: [{ role: "user", content: "Why is the sky blue?" }],
}),
});
const decoder = new TextDecoder();
let buffer = "";
for await (const bytes of res.body) {
buffer += decoder.decode(bytes, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop();
for (const line of lines) {
if (!line.trim()) continue;
const chunk = JSON.parse(line);
process.stdout.write(chunk.message.content);
if (chunk.done) process.stdout.write("\n");
}
}
Once you're past the first call, the official libraries save you the boilerplate. Ollama publishes ollama-python and ollama-js, and both talk to a local server by default.
pip install ollama
from ollama import chat
response = chat(
model="gemma4:31b",
messages=[{"role": "user", "content": "Why is the sky blue?"}],
)
print(response["message"]["content"])
npm install ollama
import ollama from "ollama";
const stream = await ollama.chat({
model: "gemma4:31b",
messages: [{ role: "user", content: "Why is the sky blue?" }],
stream: true,
});
for await (const part of stream) {
process.stdout.write(part.message.content);
}
To point either library at the cloud instead, set the host to https://ollama.com and pass your key in an Authorization: Bearer header, which is exactly what the API overview describes. The raw-HTTP versions above work against the cloud the same way: change the base URL and add the header.
Ollama API key: when you need one and when you don't#
Searches for "ollama api key local" and "how to activate ollama api" usually come from people who expect a key to exist somewhere. For a local server there isn't one. Nothing to generate, nothing to activate. Requests to http://localhost:11434 go through without any Authorization header, and that's the documented behavior, not a loophole.
A key is only needed for cloud models at https://ollama.com/api. As of October 17, 2026, the API overview says to create a key in your Ollama account, export it as OLLAMA_API_KEY, and send it as a bearer token:
curl https://ollama.com/api/chat \
-H "Authorization: Bearer $OLLAMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma4:31b",
"messages": [{"role": "user", "content": "Why is the sky blue?"}],
"stream": false
}'
The same page notes that you can also reach cloud models through your local server after signing in to Ollama, so local code can mix downloaded and hosted models without changing the base URL. On pricing: the API overview doesn't list cloud prices, so check your Ollama account page for current terms rather than relying on a number from a blog post.
One related gotcha is the OpenAI-compatible endpoint. OpenAI's client libraries refuse to start without an API key even when the server doesn't check it, so for local use set any non-empty string as the key and point base_url at http://localhost:11434/v1.
Ollama API not working: common mistakes#
Most "ollama api not responding" reports come down to one of these.
- Connection refused on port 11434. The server isn't running. Start the desktop app, or run
ollama servein a terminal, then retry the root health check. - 404 with "model not found". The
modelstring doesn't match anything in/api/tags. Tags matter:gemma4:31bandgemma4can be different entries. Pull the exact name you're requesting. - JSON parse error on the response. You parsed a stream as a single object. Either set
"stream": falseor read the body line by line as shown above. - Works with curl, fails from Docker or another machine. Inside a container,
localhostis the container itself. SetOLLAMA_HOSTto0.0.0.0:11434in the server's environment so it listens on all interfaces, then use the host's address from the client. - Browser requests blocked by CORS. The server only accepts browser origins it's configured to allow. Set
OLLAMA_ORIGINSto your app's origin in the server environment, or proxy the calls through your backend, which also keeps the API off the public internet. - The model answers as if it forgot everything. You sent only the latest user message. Send the full
messageshistory each turn. - 401 from the cloud endpoint. The
Authorizationheader is missing orOLLAMA_API_KEYis empty in that shell. Echo the variable before blaming the key. - The first request after a while is slow. The model is being loaded into memory. Keep client timeouts generous and hit
/api/psif you want to see what's currently loaded. - Mixed-up paths.
/api/chatand/v1/chat/completionstake different request shapes. Pick one API surface per client and stick with it.
Quick reference#
- Local base URL:
http://localhost:11434/api, no API key. - Cloud base URL:
https://ollama.com/api, headerAuthorization: Bearer $OLLAMA_API_KEY. - Health check:
curl http://localhost:11434printsOllama is running. - One-shot text:
POST /api/generatewithmodelandprompt; readresponse. - Conversation:
POST /api/chatwithmodelandmessages; readmessage.content; resend the full history each turn. - Streaming is on by default; parse one JSON object per line and stop at
"done": true. Add"stream": falsefor a single object. - Installed models:
GET /api/tags; use the exactnamein requests. - Libraries:
pip install ollamaandnpm install ollama, local by default, cloud by setting the host and bearer header. - Remote or container access: set
OLLAMA_HOST; browser access: setOLLAMA_ORIGINS. - Full field-level reference: the Ollama API docs on GitHub.
Quick answers
Do I need an API key to use the Ollama API?
Not for a local server. Requests to http://localhost:11434/api work with no Authorization header. A key is only required for cloud models at https://ollama.com/api, where you send it as a bearer token.
What port and URL does the Ollama API use?
A local Ollama server listens on port 11434. The native API is at http://localhost:11434/api, and the OpenAI-compatible endpoint is at http://localhost:11434/v1.
Where are the official Ollama API docs?
The overview with base URLs, authentication and library links is at docs.ollama.com/api. The field-by-field reference for every endpoint lives in the api.md file in the Ollama GitHub repository.
Why does /api/generate return many JSON objects instead of one?
Streaming is on by default, so the server writes one JSON object per line as tokens arrive. Set "stream": false in the request body to receive a single response object, or parse the body line by line.
Does the Ollama API cost anything?
Running models on your own machine through the local API is free; there's no key and no billing. Cloud models at ollama.com require an account and API key, and the API overview page doesn't list prices, so check your Ollama account for current terms.
Did this solve it?
One tap. No account.
Sorry about that. What was missing?
from 0 readers
Saved you an hour? Send a tip.
USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.
Network
0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
On a computer? Scan the code with your phone wallet, or copy the address.
Pick the network your wallet or exchange uses. USDC works on all six; ETH on Base, Ethereum, Arbitrum and Optimism. Don't send on Tron or Solana: this address doesn't exist there. Tips are optional and unlock nothing; every guide stays free.
Discussion
Start the discussion
Next note