DEV Community

Andrey Altrouter
Andrey Altrouter

Posted on

Your chatbot's average call costs $0.006 — one pasted file can make it $2.03

I priced a typical support-bot question on Claude Sonnet 5.5 at list price: $0.006. The same endpoint, with the same key and the same code, will accept a request that costs $2.03, as much as 339 typical questions at once. Nothing in the API asks whether you meant it. All it takes is one user pasting a big file into your text box.

Every request has a price ceiling

You pay per token, a chunk of text about three-quarters of an English word. Prices are quoted per million tokens, separately for input (everything you send: instructions, chat history, the user's message) and output (what the model writes back). The context window is the most tokens one request may hold. max_tokens is the request field that caps the length of the reply.

Put them together and you get the most a single request can cost: input tokens you let in × input price + max_tokens × output price.

If you don't limit the input, the first term is the whole context window. Nobody types a million tokens by hand, but three ordinary things get you there. A user pastes a log file into the chat box. A bug appends the same document to the prompt on every loop. A search step hands the model whole files instead of the relevant paragraphs. The API treats none of these as an error. If it fits the window, it's a valid request, and it's billed.

Five models, one full window

I compared a typical call (1,500 tokens in, 300 out: a system prompt, a short history and a question) with a call that fills the window and gets a 4,096-token reply. Context windows and list prices, meaning the vendors' own published per-token prices, come from the catalog of the LLM gateway I work on (snapshot of 16.10.2026), where prices sit 10–29% below list, which shrinks every dollar cell and leaves the ratio column untouched.

Model Context window Input, $/1M Typical call Full-window call Ratio
gpt-5.6-mini 400K $0.20 $0.0007 $0.08 127×
claude-sonnet-4-5 200K $3 $0.0090 $0.65 72×
gpt-5.6 400K $2 $0.0066 $0.84 127×
claude-sonnet-5.5 1M $2 $0.0060 $2.03 339×
gpt-6-astra 1.05M $10 $0.0300 $10.66 355×

The ratio doesn't follow the price. It follows the window. Across the whole catalog, every 200K model lands between 72× and 79×, and every 1M model between 258× and 375×. claude-haiku-5.5 at $0.10 per million and claude-fable-5.1 at $10 both come out at exactly 339×.

That's how an upgrade can cut your price per token and still raise your worst case. Moving from claude-sonnet-4-5 to claude-sonnet-5.5 makes input a third cheaper, and the typical call drops from $0.0090 to $0.0060. The full-window call goes from $0.65 to $2.03, because the window grew five times.

A megabyte of logs is half a million tokens

How much text fills the window depends on what's pasted, and the usual rule of thumb, four characters per token, only holds for prose. I counted with tiktoken, OpenAI's open-source tokenizer (the program that cuts text into tokens), using o200k_base, the encoding behind current GPT models.

95 KB of English articles from this blog came out at 24,434 tokens, 3% above the four-characters estimate. A synthetic one-megabyte server log came out at 529,646 tokens, 2.1 times the estimate. It's lines like 2026-10-14T09:23:18.178Z WARN req=c41f9dfd-… POST /health/66746 201 1647ms, and random hex IDs and long numbers split into many small tokens.

So one megabyte of logs is $1.06 of input on claude-sonnet-5.5 and $2.12 on claude-opus-5.5. On gpt-5.6 it doesn't fit at all: the 400K window is full at 0.76 MB, and the API answers with an error instead. The paste that costs you money is the one that just fits.

It also means a guard that counts characters lets through twice the tokens you planned for whenever someone pastes machine output.

Set the ceiling yourself, in dollars

Decide what one request may cost, and check it before sending: count the input tokens, add the reply ceiling, multiply by your model's prices, refuse anything above the limit. It needs pip install tiktoken.

import tiktoken

enc = tiktoken.get_encoding("o200k_base")  # GPT-5.x tokenizer; others differ
PRICE_IN, PRICE_OUT = 2.00, 12.00          # $ per 1M tokens, gpt-5.6 list price
MAX_TOKENS = 1_000                         # send the same value as max_tokens
MAX_USD = 0.02                             # the most one request may cost

def check(messages):
    tokens_in = sum(len(enc.encode(m["content"])) + 4 for m in messages)
    usd = (tokens_in * PRICE_IN + MAX_TOKENS * PRICE_OUT) / 1e6
    if usd > MAX_USD:
        raise ValueError(f"refused: up to ${usd:.2f}, limit ${MAX_USD:.2f}")
    return usd

print(f"ok: up to ${check([{'role': 'user', 'content': 'Where is my order?'}]):.4f}")
paste = "2026-10-14T09:23:18.178Z WARN req=c41f9dfd-b484 POST /health 201\n" * 5_000
try:
    check([{"role": "user", "content": paste}])
except ValueError as e:
    print(e)
Enter fullscreen mode Exit fullscreen mode

It prints ok: up to $0.0120, then refused: up to $0.32, limit $0.02. The 325 KB paste never reaches the API, so it costs nothing. The + 4 is a rough allowance for the few tokens of wrapping each message carries.

Look at where the short question's $0.012 comes from: almost all of it is max_tokens, 1,000 reply tokens at $12 per million. If your bot usually answers in 300 tokens, a lower max_tokens is the cheaper lever. At these settings the guard leaves room for 4,000 input tokens, about 2,700 words. If that's too tight, raise the limit. What matters is that it's a number you picked. Instead of refusing, you can also trim the paste to fit and tell the user.

What this doesn't solve

tiktoken is OpenAI's tokenizer. Claude and Gemini split text differently, so on those models treat the count as an estimate and keep a margin. A per-request ceiling also says nothing about how many requests arrive: a runaway loop stays under the limit every single time. That needs a daily cap. Caps have a gap of their own: a request's price is known only after the reply ends, so spend limits are usually checked before a request and charged after it. Ours works that way too, and the request that crosses the limit is still billed in full.

The takeaway

Until you set a lower one, the context window is the price ceiling of every request. Pick a dollar limit, count tokens rather than characters, and check before you send.

Top comments (0)