← Code Recipes
Hosting, Gateways & Local

Ollama Free code examples in C#, Python, Java and JavaScript

Run open models locally with one command and an OpenAI-compatible endpoint.

C# Python Java JavaScript

WHAT THIS PAGE COVERS

Pointing an existing OpenAI client at localhost — usually a one-line change.

Model gpt-oss:20b
Package openai
Checked

Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.

Install

The official OpenAI package plus an endpoint override. Nothing Ollama-specific.

ollama pull gpt-oss:20b
dotnet add package OpenAI
Point an OpenAI client at localhost

OpenAIClientOptions.Endpoint is the whole change. ApiKeyCredential still needs a value; Ollama ignores it.

using System.ClientModel;
using OpenAI;
using OpenAI.Chat;

// Required by the client, ignored by the server.
var placeholder = new ApiKeyCredential("ollama");

var options = new OpenAIClientOptions
{
    Endpoint = new Uri("http://localhost:11434/v1/"),
};

ChatClient chat = new("gpt-oss:20b", placeholder, options);

ChatCompletion completion = await chat.CompleteChatAsync(
    "Explain a database index in two sentences.");

Console.WriteLine(completion.Content[0].Text);
One registration, either destination

In DI this is a single factory. Swapping a hosted model for a local one becomes a configuration change rather than a code change — which is the argument for keeping the OpenAI shape at all.

builder.Services.AddSingleton<ChatClient>(services =>
{
    var config = services.GetRequiredService<IConfiguration>();

    if (config.GetValue<bool>("UseLocal"))
    {
        return new ChatClient(
            "gpt-oss:20b",
            new ApiKeyCredential("ollama"),
            new OpenAIClientOptions { Endpoint = new Uri("http://localhost:11434/v1/") });
    }

    var hosted = config["OLLAMA_API_KEY"];
    if (!string.IsNullOrEmpty(hosted))
    {
        return new ChatClient(
            "gpt-oss:120b",
            new ApiKeyCredential(hosted),
            new OpenAIClientOptions { Endpoint = new Uri("https://ollama.com/v1") });
    }

    return new ChatClient("gpt-5.4-mini", config["OPENAI_API_KEY"]!);
});
Timeouts, which the default gets wrong

A local model on a cold start can take a minute before the first token. The .NET default of 100 seconds is survivable; the retry policy on top of it is what turns one slow load into three.

var options = new OpenAIClientOptions
{
    Endpoint = new Uri("http://localhost:11434/v1/"),
    NetworkTimeout = TimeSpan.FromMinutes(5),

    // A cold model load is not a transient failure. Retrying it
    // starts a second load on a machine already saturated by the
    // first, and both get slower.
    RetryPolicy = new ClientRetryPolicy(maxRetries: 0),
};
Install

Pull a model once and it is cached on disk. gpt-oss:20b wants about 16GB of RAM; qwen3:8b runs comfortably on a laptop.

# https://ollama.com/download, then:
ollama pull gpt-oss:20b
ollama pull qwen3:8b

ollama list
ollama run qwen3:8b "Explain a database index in two sentences."

pip install openai
Point an OpenAI client at localhost

THIS IS THE WHOLE MIGRATION. Same package, same method, same response shape — only base_url changed. The key is required by the client and ignored by the server.

from openai import OpenAI

# Required by the client, ignored by Ollama. Not a real credential,
# so nothing valuable ends up in a config pointing at localhost.
PLACEHOLDER_KEY = "ollama"

client = OpenAI(
    base_url="http://localhost:11434/v1/",
    api_key=PLACEHOLDER_KEY,
)

response = client.chat.completions.create(
    model="gpt-oss:20b",
    messages=[{"role": "user", "content": "Explain a database index."}],
)

print(response.choices[0].message.content)
One switch between local and hosted

Because the API is the same, the choice is a factory rather than a fork through the codebase. This is the shape worth writing on day one — it costs nothing and it is what makes a local model a real option later.

import os

def build_client():
    if os.environ.get("USE_LOCAL"):
        # Anything on your machine, at no cost per token.
        return OpenAI(
            base_url="http://localhost:11434/v1/",
            api_key=PLACEHOLDER_KEY,
        ), "gpt-oss:20b"

    if os.environ.get("OLLAMA_API_KEY"):
        # Ollama's own hosted service — same API, bigger machines.
        return OpenAI(
            base_url="https://ollama.com/v1",
            api_key=os.environ["OLLAMA_API_KEY"],
        ), "gpt-oss:120b"

    return OpenAI(), "gpt-5.4-mini"

client, model = build_client()
Tools and structured output work too

Not every local model supports tool calling — check the model card first. When it does, the request and response shapes are identical to OpenAI's, so the calling code does not change.

tools = [{
    "type": "function",
    "function": {
        "name": "get_stock",
        "description": "Get the stock level for a product code.",
        "parameters": {
            "type": "object",
            "properties": {"code": {"type": "string"}},
            "required": ["code"],
        },
    },
}]

response = client.chat.completions.create(
    model="gpt-oss:20b",
    messages=[{"role": "user", "content": "How many X-17 are in stock?"}],
    tools=tools,
)

call = response.choices[0].message.tool_calls[0]
print(call.function.name, call.function.arguments)
Knowing what the box can actually run

A model that does not fit in RAM is swapped to disk and becomes unusably slow rather than failing. Check before you deploy, not after the first complaint.

# What is loaded right now, and how much it is using.
ollama ps

# Everything available locally, with sizes.
ollama list

# Rough guide: the file size is the floor for RAM, plus context.
#   qwen3:8b      ~5GB   comfortable on a 16GB laptop
#   gpt-oss:20b   ~14GB  wants 32GB to be pleasant
#   gemma4:31b    ~20GB  a workstation, not a laptop
#
# Over the limit it does not error — it swaps, and a reply that took
# two seconds takes two minutes.
Install

The official openai-java client takes a base URL. No Ollama-specific dependency exists or is needed.

ollama pull gpt-oss:20b

# Gradle
implementation("com.openai:openai-java:4.42.0")
Point an OpenAI client at localhost

baseUrl plus a placeholder key. Everything after this line is the same code you would write against OpenAI.

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

public class Local {
    public static void main(String[] args) {
        OpenAIClient client = OpenAIOkHttpClient.builder()
            .baseUrl("http://localhost:11434/v1/")
            // Required by the client, ignored by Ollama.
            .apiKey("ollama")
            .build();

        ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
            .model("gpt-oss:20b")
            .addUserMessage("Explain a database index in two sentences.")
            .build();

        client.chat().completions().create(params).choices()
            .forEach(choice -> System.out.println(choice.message().content().orElse("")));
    }
}
One factory, either destination

The switch lives in one method. Everything downstream holds an OpenAIClient and does not care which machine answers it.

static OpenAIClient buildClient() {
    if (System.getenv("USE_LOCAL") != null) {
        return OpenAIOkHttpClient.builder()
            .baseUrl("http://localhost:11434/v1/")
            .apiKey("ollama")
            .build();
    }

    String hosted = System.getenv("OLLAMA_API_KEY");
    if (hosted != null) {
        return OpenAIOkHttpClient.builder()
            .baseUrl("https://ollama.com/v1")
            .apiKey(hosted)
            .build();
    }

    // Reads OPENAI_API_KEY.
    return OpenAIOkHttpClient.fromEnv();
}
Timeouts for a cold model

The first request after a pull loads gigabytes from disk. A default timeout plus automatic retries turns that into several concurrent loads on the same machine, which is slower than waiting.

import java.time.Duration;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .baseUrl("http://localhost:11434/v1/")
    .apiKey("ollama")
    .timeout(Duration.ofMinutes(5))
    // A cold load is not transient. Retrying it makes it worse.
    .maxRetries(0)
    .build();
Install

The official OpenAI package works unchanged. Nothing Ollama-specific is installed on the client side.

ollama pull gpt-oss:20b
npm install openai
Point an OpenAI client at localhost

Same package, same call, same response. The base URL is the only difference between this and a hosted model.

import OpenAI from "openai";

// Required by the client, ignored by Ollama.
const placeholderKey = "ollama";

const client = new OpenAI({
  baseURL: "http://localhost:11434/v1/",
  apiKey: placeholderKey,
});

const response = await client.chat.completions.create({
  model: "gpt-oss:20b",
  messages: [{ role: "user", content: "Explain a database index." }],
});

console.log(response.choices[0].message.content);
One switch between local and hosted

A factory rather than a branch in every call site. Writing it early is what keeps a local model from being a rewrite later.

function buildClient() {
  if (process.env.USE_LOCAL) {
    return [
      new OpenAI({ baseURL: "http://localhost:11434/v1/", apiKey: placeholderKey }),
      "gpt-oss:20b",
    ];
  }

  if (process.env.OLLAMA_API_KEY) {
    return [
      new OpenAI({
        baseURL: "https://ollama.com/v1",
        apiKey: process.env.OLLAMA_API_KEY,
      }),
      "gpt-oss:120b",
    ];
  }

  return [new OpenAI(), "gpt-5.4-mini"];
}

const [client, model] = buildClient();
Streaming, and the first-token cost

The first request after a pull loads the model into memory, which can take many seconds. Streaming makes that visible; a keep-alive stops it happening on every request.

const started = Date.now();
let firstTokenAt = null;

const stream = await client.chat.completions.create({
  model: "gpt-oss:20b",
  messages: [{ role: "user", content: "Explain B-trees in 200 words." }],
  stream: true,
});

for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) {
    firstTokenAt ??= Date.now() - started;
    process.stdout.write(delta);
  }
}

// A large first number is the model loading, not the model thinking.
// `ollama run <model> --keepalive 60m` holds it in memory.
console.log(`\nfirst token after ${firstTokenAt}ms`);

QUESTIONS

Which languages are the Ollama examples in?

C#, Python, Java and JavaScript. Every sample runs as pasted and reads its credentials from an environment variable — no key is ever written into the code.

Which package do I install for Ollama?

The samples use openai. The install step on each language tab gives the exact command.

Which Ollama model do these examples use?

gpt-oss:20b, checked against the official documentation on 26 September 2026. Model ids change often; if a call returns a model-not-found error, check the current list in the official docs.

Where is the official Ollama documentation?

https://github.com/ollama/ollama/blob/main/docs/api.md — it is linked at the bottom of this page, and it is the authority whenever it disagrees with a sample here.

ALSO IN HOSTING, GATEWAYS & LOCAL

The authority

Official Ollama documentation

Model names, pricing and rate limits change faster than any page here can. When this page and the official docs disagree, the official docs are right.

Read the docs ↗

https://github.com/ollama/ollama/blob/main/docs/api.md

New drops, every week

Free tools & Claude templates, landing regularly.

We keep shipping new free tools, code recipes and Claude Code templates. Follow @freeyantra on Instagram or join the newsletter so you never miss one.

Follow @freeyantra

or get them by email

Double opt-in. Unsubscribe any time. Privacy