Skip to main content

ctok

ctok reconstructs Claude token counts offline, with no API call, network access, or runtime dependencies. It is unofficial and is not affiliated with Anthropic.

The reconstruction targets counts. Claude does not expose token boundaries, so tokenize() returns one valid minimum-cost tiling, not a claim about Anthropic's exact segmentation. The research behind the model is described in On the biology of Claude's tokenizer.

Count a string

ctok is on PyPI, so uvx fetches and runs it with no install. With no --version it reports both generations, since the same string does not cost the same on each.

uvx ctok "hello, world"
  v3.0
  stream: '⟨bow⟩hello⟨eow⟩,⟨eow⟩⟨bow⟩world⟨eow⟩'
  tokens: ['⟨bow⟩hello⟨eow⟩', ',⟨eow⟩', '⟨bow⟩world⟨eow⟩']

  content 3 + frame 7 = 10

  v5.0
  stream: '⟨bow⟩hello⟨eow⟩,⟨eow⟩⟨bow⟩world⟨eow⟩'
  tokens: ['⟨bow⟩h', 'ello⟨eow⟩', ',⟨eow⟩', '⟨bow⟩world⟨eow⟩']

  content 4 + frame 6 = 10

--version 4.7 picks one family instead.

As a library

from ctok import token_count, tokenize

token_count("hello, world")           # 10, using the v3 family
token_count("hello, world", "4.7")    # 15
token_count("hello, world", "5.0")    # 10

tokens = tokenize("NASA likes tokenizers")
assert len(tokens) == token_count("NASA likes tokenizers")

Supported families

version is a string such as "4.7". Components are compared as integers, so "4.10" sorts after "4.9". Python reads the float literal 4.10 as 4.1, so passing a non-string version raises TypeError.

requested version family model generation
"3.0" <= version < "4.7" v3, the default Claude 3 through Opus 4.6
"4.7" <= version < "5.0" v4.7 Opus 4.7 through 4.9
version >= "5.0" v5 Opus 5 and Sonnet 5

v5 uses the v4.7 vocabulary with a different message frame.

How it works

For one user message, ctok:

  1. normalizes the text, including NFC and family-specific quote folding;
  2. rewrites it into a stream with word, case, and byte markers;
  3. finds a minimum-cost tiling over the measured vocabulary and UTF-8 byte fallback;
  4. adds the measured message frame.

token_count(text) is len(tokenize(text)). The output notation makes internal structure visible:

notation meaning
⟨bow⟩, ⟨eow⟩ word boundaries
⟨shift⟩, ⟨caps⟩ case rewrites
⟨0xNN⟩ a byte-fallback token
⟨pad⟩ part of the single-message frame

Measured accuracy

These results compare ctok with recorded count_tokens responses:

corpus role v3 exact v4.7 exact
Goldfish, 350 languages and 962,054 rows mining 962,053 962,054
MultiPL-E, 22 programming languages held out 22 22
Rosetta Code, 1,741 documents mining 1,741 1,741
Rosetta Code, separate 250 documents held out 250 250
UDHR, 501 languages mining (in-sample since 2026-08-12) 501 501

v5 is omitted from the table because its deviation from recorded counts matches v4.7's on every gated document. Separate API tests cover its message-frame rules.

The stored measurement sets contain no under-counts: 0 of 2,276,929 v3 texts and 0 of 2,328,425 v4.7 texts. This does not guarantee the result for arbitrary input. Goldfish, the main Rosetta sample, and UDHR informed piece selection. MultiPL-E and the separate Rosetta sample did not.

Run the public gates with:

uv run pytest
uv run python tests/gates.py

Vocabulary evidence

The two vocabulary files contain 48,792 v3 pieces and 15,283 v4.7 pieces. Every entry has a fixed membership witness or is one of the structural marker atoms checked by the test suite.

from ctok import pieces, witness

len(pieces("4.7"))                       # 15283
witness("⟨bow⟩the⟨eow⟩", "4.7")
# {'probe': 'the', 'raw': 12, 'kind': 'raw'}

A witness says that one marked piece costs one token in a calibrated probe. It does not prove the encoder rewrite or resolve ties between equal-cost tilings. tests/test_witness.py checks every published witness and requires complete witnessed-or-special coverage.

License

MIT

Metadata

Release files for ctok 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ctok 1.2.0
File Size Uploaded
ctok-1.2.0.tar.gz 3.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for ctok 1.2.0
File Interpreter ABI Platform
ctok-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.5 MB

Release files / ctok-1.2.0.tar.gz

Download URL ctok-1.2.0.tar.gz
Size 3.1 MB
Tags Source
SHA-256 checksum
How to use checksums
13a91993db2458153303aec3d14d4e34f7ea914a61df0f93f553dc180c5d5a97
BLAKE2b-256 checksum
How to use checksums
9be2ab0dc570d703b2318b6840ff45d10ddb9d7526e80b1ba816c86e472b48bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.

Transparency log

Release files / ctok-1.2.0-py3-none-any.whl

Download URL ctok-1.2.0-py3-none-any.whl
Size 464.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b4b13af451f1e88a42dcda5e8e44b216b2da371f401403c490079bbaf4d5c028
BLAKE2b-256 checksum
How to use checksums
bfe544639f985578fd09f8cf68824bacd863b109138c25d81e4b39356b8f6f36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.

Transparency log

Release history Release notifications | RSS feed

1.3.0

2 release files

This release

1.2.0 This release

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page