lumo

Module 01 · Lesson 4 of 13Free

Tokens: how models read text and charge for it

Level
Beginner
Topic
AI engineering fundamentals
Reading time
8 min

When you finish this page you can

  1. Explain what a token is and why a message has more tokens than words.
  2. Predict which texts take more tokens for the same meaning, such as other languages, code and numbers.
  3. Name what a model API counts in tokens, thinking included, and what each count controls.
  4. Count a request’s tokens before sending it, with the token counting endpoint in Python.
  1. Calling a model API: request, response and cost15 min

Video lesson · coming soon

A 38-word message is not 38 tokens

Deskora is a help desk app. A shop’s support team uses it to answer customer emails from one shared inbox. Each customer problem becomes a ticket: one customer’s conversation with the support team. Tomás, a Deskora engineer, is building a short summary for long tickets.

Here is the first message of one ticket, from a customer named Meera:

Hi, I ordered a pressure cooker on 12 March (order 58214) and it has not arrived yet. The tracking page says it is in transit, but nothing has changed for six days. Can you check where it is?

It has 38 words. But the model API bills tokens, not words. Tomás’s estimate of about $38 a day for summaries, in Calling a model API, rests on a guess: about 4,000 tokens per thread.

Check yourselfAnswer in your head first, then reveal
Meera’s message has 38 words. Will Claude count about 38 tokens, fewer, or more?Show answerHide answer
More. Common words are often one token each, but punctuation, numbers and less common words add pieces. In this lesson’s illustrative split it is 47. Not “one token per word”: a token is often part of a word.

This lesson answers one question: what exactly is Tomás paying for, and how can he count it before he sends a ticket? The token counts here are illustrative; the code near the end gives real ones.

A token is a common piece of text

Before the model sees Meera’s message, a tokenizer cuts it into tokens: pieces of text from a fixed list called the vocabulary. Each token becomes a number, and the model reads and writes those numbers, as Next-token prediction shows.

Diagram not drawn yet: deskora-message-token-split.svg

Meera’s 38-word message drawn as a row of 47 small boxes, one per token. Most words, each with its leading space, are one box: Hi, I, ordered, pressure, tracking. The word cooker is two boxes, cook and er. The order number 58214 is two boxes, 582 and 14. Each comma, full stop, bracket and the question mark is its own box. A note says the split is illustrative because Claude’s tokenizer is not public.

One illustrative split of Meera’s message: 38 words become 47 tokens. Common words are one token; rarer words, numbers and punctuation add pieces.

Why pieces, and not words or letters? A vocabulary of whole words would need every name, typo and order number, and would still miss new ones. Single characters make every message several times longer, and the model’s work grows with length. Tokens sit between: frequent words get one token, and everything else is built from several.

Anthropic doesn’t publish the tokenizer for current Claude models, so the real boundaries may differ. Only the API gives you a real count.

The same meaning, very different counts

The same shop also gets tickets in Hindi. Here is Meera’s message, translated:

नमस्ते, मैंने 12 मार्च को एक प्रेशर कुकर ऑर्डर किया था (ऑर्डर 58214), लेकिन वह अभी तक नहीं पहुँचा है। ट्रैकिंग पेज पर लिखा है कि वह रास्ते में है, पर छह दिनों से कुछ नहीं बदला। क्या आप पता कर सकते हैं कि वह कहाँ है?

Check yourselfAnswer in your head first, then reveal
The Hindi version has only 24 more characters than the English one. Will it take about the same number of tokens?Show answerHide answer
No. In this lesson’s illustrative counts it takes about 130 tokens against 47, nearly three times as many. A tokenizer gives its own tokens to text it saw often when it was built, and builds other scripts from smaller pieces.

A common rule says “a token is about three-quarters of a word”. It breaks for other languages, code and numbers: the count depends on the tokenizer, the language and the type of content 2.

Sample Characters Tokens (illustrative) Tokens per 100 characters
Meera’s message, English 191 47 25
The same message, Hindi 215 130 60
Two lines of Python 112 30 27
Order line with IDs and dates 102 46 45

This gap is not special to Claude. One study found the same text in different languages up to 15 times apart in tokens 3. The model matters too: Claude models from 4.7 on use a newer tokenizer that produces about 30% more tokens for the same text 2.

Price, context and max_tokens all count tokens

What Counted in tokens
Price Input tokens at the input price, plus output tokens at the output price
Output Thinking plus the visible text, both billed as output 4
max_tokens The ceiling on output tokens, thinking included
Context window All the tokens one call can hold

Here is lesson 03’s cost formula applied to a Hindi ticket. Claude Haiku 5.5 costs $0.10 per million input tokens and $0.50 per million output tokens, as of October 2026 2.

English thread (from lesson 03)

4,150 × $0.10 ÷ 1,000,000 + 380 × $0.50 ÷ 1,000,000 = $0.000605

4,150 input tokens. Assumed: 300 thinking tokens and an 80-token summary.

The same thread in Hindi

4,000 tokens × 2.8 = 11,200 tokens; + 150 system = 11,350 input tokens

This lesson’s illustrative ratio. The summary stays in English, so output is unchanged.

Cost of one Hindi summary

11,350 × $0.10 ÷ 1,000,000 + 380 × $0.50 ÷ 1,000,000 = $0.001135 + $0.00019 = $0.001325

About 2.2 times the English summary.

If Deskora charges every shop the same, a shop with mostly Hindi tickets costs about twice as much to serve; Charging for AI features deals with that. The Hindi thread also fills nearly three times as much of the context window, covered in Context windows. One ratio can’t serve every ticket, so Tomás needs a real count.

Count tokens before you send

How should Tomás learn a ticket’s token count before he sends it?

Estimate from characters or words with a fixed ratio.

Free and instant, but wrong by a different amount for each language and type of text. A ratio taken from Meera’s English message predicts about 53 tokens for the Hindi one, less than half of 130.

Run another provider’s tokenizer library on his server.

Exact for the models it was made for, and wrong for Claude. A library such as tiktoken counts with OpenAI’s tokenizers, which split text differently.

Send the call and read usage afterwards.

Exact, because every response reports usage. But it arrives after Deskora has paid, so it can’t change the request.

Why this choice

Only the API uses Claude’s own tokenizer before money is spent. Counting is free, with its own rate limit: 5,000 requests a minute on the lowest usage tier, as of October 2026 1. Still log usage after every call: that is the billed number.

When the choice changes. Count first only when a decision depends on the count. On Claude Haiku 5.5, a prompt over 100,000 tokens pays five times the price per token 2, so a count near that line matters. For millions of small, similar calls, a ratio per language from your own logged usage is often close enough.

Diagram not drawn yet: count-then-send.svg

Left to right. 1: the Deskora app server sends the system prompt and thread to POST /v1/messages/count_tokens, labelled free. 2: a dashed reply returns input_tokens 11,350. 3: a decision box asks whether the count is over 100,000 tokens; the no branch continues. 4: the app server sends the same request to POST /v1/messages, labelled billed. 5: a dashed reply returns the summary and usage, with input_tokens about 11,350, labelled the billed count, to log.

Count first when a decision depends on the number, then log usage, the count you are billed for.

The endpoint, POST /v1/messages/count_tokens, takes the same model, system and messages as a normal call and returns one field, input_tokens 1. It counts input only: output, thinking included, is unknown until the model writes it.

python
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from the environment

MODEL = "claude-haiku-5-5"
INPUT_PRICE = 0.10  # US dollars per million input tokens, as of October 2026
LONG_PROMPT = 100_000  # above this, Haiku 5.5 charges 5 times per token
SYSTEM = (
    "You summarize a support ticket for the agent who picks it up. "
    "Write exactly three lines: the problem, what has been tried, "
    "and what the customer is waiting for."
)


def count_summary_input(thread: str) -> int:
    result = client.messages.count_tokens(
        model=MODEL,
        system=SYSTEM,
        messages=[{"role": "user", "content": thread}],
    )
    return result.input_tokens


if __name__ == "__main__":
    with open("ticket.txt", encoding="utf-8") as f:
        thread = f.read()
    tokens = count_summary_input(thread)
    cost = tokens * INPUT_PRICE / 1_000_000
    print(f"{len(thread)} characters, {tokens} input tokens, ${cost:.6f} of input")
    if tokens > LONG_PROMPT:
        print("Over 100,000 tokens: this call would pay the long-prompt price.")

Running it costs nothing, because counting is free; you need an . Put Meera’s message in ticket.txt in English, then in Hindi, and compare.

Reusing a token count from another model

Tokenizers change between model generations, so a count from one model can be wrong for another. Anthropic advises recounting with the model you plan to use 1.

Tomás can now count a ticket’s tokens. The model they go to sets the price of each one, which is the subject of Choosing a model.

Check your understanding

Check yourselfAnswer in your head first, then reveal
A shop’s customers switch from writing in English to writing in Hindi. The number of tickets stays the same. What happens to the cost of their summaries, and why?Show answerHide answer
It rises, to about 2.2 times per summary with this lesson’s illustrative numbers, because the same thread takes more input tokens. Not a higher price: the price per token is unchanged; only the count grew.
Check yourselfAnswer in your head first, then reveal
A summary takes 80 tokens in English. Tomás asks for it in Hindi, with max_tokens set to 400 and about 300 thinking tokens. What can go wrong?Show answerHide answer
The Hindi summary may take about 220 tokens, and 300 thinking plus 220 text is more than 400, so the call stops with stop_reason max_tokens and a cut-off summary. Not the context window: max_tokens limits output only, thinking included.
Check yourselfAnswer in your head first, then reveal
Tomás counts a ticket with count_tokens, then sends it. usage.input_tokens is 3 tokens higher than the count. Is that a bug?Show answerHide answer
No. The token counting endpoint returns an estimate that can differ from the billed number by a small amount. Log usage, because that is what Deskora pays for.

Summary

  1. Tomás pays for tokens, pieces of text often smaller than words, and counts them before sending with the free client.messages.count_tokens.
  2. Common words are one token; rare words, numbers and other scripts take several.
  3. The same meaning can take very different counts: Hindi nearly three times English, in this lesson’s illustrative numbers.
  4. Price, the context window and max_tokens are all counted in tokens, thinking included.
  5. Count with the model you will use, not a fixed ratio or another provider’s tokenizer, and log usage for the billed number.

Report a mistake

Tell us what’s wrong in this lesson and we’ll fix it.