Guide · Ollama · API

Ollamas API: ditt första anrop med curl och Python

Prata direkt med den lokala servern: kontrollera att den svarar, skicka en prompt och ett samtal, läs tidsfälten och bekräfta att porten bara nås från den egna datorn.

Av C. Leijon · Publicerad · Senast granskad · 7 min läsning

En låg svart metallåda med handtag och ventilationsgaller står på ett mörkt trägolv framför en svart vägg. En svart kabel går från lådans framsida ut åt vänster, och två små gröna lampor lyser och speglas i golvet.
Ollama svarar på port 11434 på den egna datorn. Steg 6 visar hur du kontrollerar att ingen annan når porten.

Många artiklar här på AI-burken skickar anrop till /api/chat eller /api/generate och läser fält som eval_count. Den här guiden är grunden under dem. Du gör ett anrop från terminalen och samma anrop från ett kort Python-skript, och du avslutar med att kontrollera att servern bara lyssnar lokalt. Allt sker mot Ollamas lokala server på port 11434; ingen molnnyckel behövs.

Så testades guiden

Fältnamn och standardvärden följer Ollamas API-dokumentation som den såg ut 10 oktober 2026, när v0.40.2 (8 oktober 2026) var senaste release. På redaktionens dator fanns ingen Ollama-server och ingen Python-installation, så inget kommando nedan är kört mot Ollama. Alla svar som visas är exempel med påhittade värden. Notera din egen version i steg 1; Ollama skriver själv att API:et inte är strikt versionerat men ska vara bakåtkompatibelt.

1. Svarar servern? /api/version och /api/tags

Utgångsläget är en fungerande Ollama-installation. Saknar du den, börja med installationsguiden för Windows. Öppna sedan PowerShell. Skriv curl.exe med ändelsen: i Windows PowerShell 5.1 är curl utan ändelse ett alias för Invoke-WebRequest, som tar andra flaggor och ger andra fel.

curl.exe -s http://localhost:11434/api/version
curl.exe -s http://localhost:11434/api/tags

Facit för det första anropet är ett JSON-objekt med fältet version. Skriv ned värdet; det är versionen du faktiskt testar mot. Exempel på hur svaret ser ut:

{"version":"0.40.2"}

Det andra anropet listar modellerna du har lokalt i en lista models. Varje post har bland annat name, size i byte och ett details-objekt med parameterstorlek och kvantisering. Kopiera ett name; det är vad du skriver i fältet model i resten av guiden. Exemplen nedan använder gemma4 eftersom Ollamas egna exempel gör det. Byt mot ditt eget namn. En tom lista betyder att servern svarar men att ingen modell är hämtad. Får curl inget svar alls, med felkod 7, lyssnar ingen server på adressen: starta Ollama-appen och försök igen.

2. Första anropet med curl: /api/generate

/api/generate tar en fristående prompt och returnerar text. Det kräver bara model; prompt är texten modellen ska svara på. Enligt referensen för generate har stream standardvärdet true, så du får svaret i bitar om du inte säger något annat.

En fallgrop i Windows PowerShell 5.1 är citattecknen. JSON skrivet direkt efter -d kan tappa sina dubbla citattecken på vägen till curl.exe. Skriv därför kroppen till en fil och låt curl läsa den med @. Använd WriteAllText: Microsoft dokumenterar att den skriver UTF-8 utan BOM, medan Out-File och > i 5.1 skriver UTF-16 och -Encoding UTF8 lägger till en BOM. Kör kommandona i en mapp där du får skriva filer.

$gen = '{"model": "gemma4", "prompt": "Förklara vad en token är på två meningar."}'
[System.IO.File]::WriteAllText("$PWD\generate.json", $gen)
curl.exe -s http://localhost:11434/api/generate -d "@generate.json"

Facit: terminalen fylls med många korta rader. Varje rad är ett eget JSON-objekt med ett textfragment i response och "done":false. Den sista raden har "done":true och ett done_reason. Formatet heter radavgränsad JSON (application/x-ndjson) och beskrivs på Ollamas sida om strömning. Exempel, förkortat:

{"model":"gemma4","created_at":"2026-10-10T09:00:00Z","response":"En","done":false}
{"model":"gemma4","created_at":"2026-10-10T09:00:00Z","response":" token","done":false}
...
{"model":"gemma4","created_at":"2026-10-10T09:00:02Z","response":"","done":true,"done_reason":"stop", ...}

Svarar servern med ett felmeddelande om att modellen inte finns, är namnet i model inte exakt det som /api/tags visade. Jämför tecken för tecken, inklusive taggen efter kolon.

3. Ett samtal med /api/chat

Skillnaden mot generate är formen på indata. /api/chat tar en lista messages där varje meddelande har role och content. Enligt referensen för chat är rollerna system, user, assistant och tool; den sista används för verktygsanrop och behövs inte här. Servern håller inte samtalet åt dig mellan anropen. Vill du ställa en följdfråga skickar du med hela historiken igen, inklusive modellens tidigare svar som ett meddelande med rollen assistant.

$chat = '{"model": "gemma4", "messages": [{"role": "system", "content": "Svara kort på svenska."}, {"role": "user", "content": "Vad används port 11434 till?"}]}'
[System.IO.File]::WriteAllText("$PWD\chat.json", $chat)
curl.exe -s http://localhost:11434/api/chat -d "@chat.json"

Även det här svaret strömmar som standard. Skillnaden syns i varje rad: textfragmentet ligger i message.content i stället för i response, och message.role är assistant. Använd generate för enstaka prompter utan historik och chat när du bygger något som ska föra en dialog eller skicka en systemprompt separat.

4. Stäng av strömningen och läs tidsfälten

För skript och mätningar är ett samlat svar lättare att hantera. Lägg till "stream": false i kroppen. Då kommer svaret som ett samlat JSON-objekt där texten ligger i message.content och tidsfälten står bredvid. Skriv om filen och kör igen:

$chat = '{"model": "gemma4", "stream": false, "messages": [{"role": "system", "content": "Svara kort på svenska."}, {"role": "user", "content": "Vad används port 11434 till?"}]}'
[System.IO.File]::WriteAllText("$PWD\chat.json", $chat)
curl.exe -s http://localhost:11434/api/chat -d "@chat.json"

Sidan om användningsfält anger att alla tidsvärden är i nanosekunder. Dela med 1 000 000 000 för sekunder. Exemplet nedan har påhittade värden och visar bara hur fälten hänger ihop:

FältVad det mäterPåhittat exempel
total_durationHela anropet2 300 000 000 ns = 2,3 s
load_durationAtt läsa in modellen500 000 000 ns = 0,5 s
prompt_eval_countToken i prompten22 token
prompt_eval_durationAtt bearbeta ej cachade prompttoken120 000 000 ns = 0,12 s
eval_countGenererade token48 token
eval_durationAtt generera dem1 600 000 000 ns = 1,6 s

Genereringstakten räknar du själv: eval_count delat med eval_duration i sekunder, här 48 / 1,6 = 30 token per sekund. Dokumentationen ger ingen färdig formel; det är en omräkning av enheterna. Kör samma anrop två gånger och jämför load_duration. Är den stor första gången och nära noll andra gången låg modellen redan i minnet vid andra anropet. Hur du skiljer laddning, promptbehandling och generering åt i en riktig mätning går artikeln om kallstart igenom. Svaret kan också innehålla prompt_eval_cached_count, antalet prompttoken som lästes från cache.

5. Samma anrop från Python

Skriptet nedan skickar exakt samma kropp som curl-anropet i steg 4 och använder bara Pythons standardbibliotek, så du behöver inte installera något paket. Spara det som ollama_chat.py och kör python ollama_chat.py. Tidsgränsen på 300 sekunder ger utrymme för en kall modell som först ska läsas in.

import json
import urllib.request

body = {
    "model": "gemma4",
    "stream": False,
    "messages": [
        {"role": "system", "content": "Svara kort på svenska."},
        {"role": "user", "content": "Vad används port 11434 till?"},
    ],
}
req = urllib.request.Request(
    "http://localhost:11434/api/chat",
    data=json.dumps(body).encode("utf-8"),
    headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=300) as resp:
    svar = json.load(resp)

print(svar["message"]["content"])
sekunder = svar["eval_duration"] / 1e9
print(f'{svar["eval_count"]} token på {sekunder:.2f} s = {svar["eval_count"] / sekunder:.1f} token/s')

Facit är modellens svar på en rad följt av en rad med antal token, sekunder och takt. Lägg märke till False med stor bokstav: det är Pythons värde, och json.dumps gör om det till JSON:s false. Glömmer du "stream": False får du tillbaka radavgränsad JSON, och json.load stoppar med ett tolkningsfel eftersom svaret inte är ett objekt. Vill du tvinga svaret till ett bestämt format är fältet format nästa steg; artikeln om strukturerad utdata visar hur du sätter ett JSON-schema på samma anrop.

6. Vem kan nå port 11434?

Ollamas FAQ anger att servern som standard binder 127.0.0.1 port 11434, och att variabeln OLLAMA_HOST ändrar det. Det spelar roll, eftersom det lokala API:et inte kräver autentisering: den som når porten kan köra dina modeller. Lita inte på standardvärdet, utan kontrollera vad som faktiskt gäller:

Get-NetTCPConnection -LocalPort 11434 -State Listen | Select-Object LocalAddress,LocalPort
[Environment]::GetEnvironmentVariable("OLLAMA_HOST", "User")
[Environment]::GetEnvironmentVariable("OLLAMA_HOST", "Machine")

Facit: LocalAddress är 127.0.0.1 och de två variabelraderna är tomma. Då nås API:et bara från den egna datorn. Ser du 0.0.0.0, :: eller en privat adress som 192.168.x.x har någon satt OLLAMA_HOST, och servern kan nås från nätet i den mån brandväggen släpper igenom trafiken. Avsiktlig delning med en bestämd dator, med brandväggsregel och återställning, beskriver guiden om Ollama på lokalt nätverk. Skriv in version, modellnamn och bindadress i ditt driftkort.

Källor

Källorna kontrollerades 10 oktober 2026. Inget kommando i guiden har körts mot en Ollama-server: redaktionens dator saknade både Ollama och Python vid kontrollen. Exempelsvar och tidsvärden är påhittade för att visa formen. Kontrollera guiden igen när Ollama ändrar API-referensen för generate, chat eller usage.

Nästa steg

Spara version, modellnamn och bindadress från proven ovan där nästa person hittar dem.

Öppna driftkortet