Comment compter les tokens et estimer les coûts d'API des LLM
Comptez les tokens LLM avec précision et estimez les coûts API avec les tokenizers OpenAI, Claude, Gemini et Llama, plus des conseils de fenêtre de contexte et de facturation.
Pour compter les tokens avec précision, faites passer l’intégralité du corps de la requête dans le tokenizer du modèle que vous appelez réellement, puis estimez le coût selon la formule (input_tokens ÷ 1 000 000) × input_rate + (output_tokens ÷ 1 000 000) × output_rate, en reprenant les tarifs actuels indiqués sur la page de tarification du fournisseur.
Personne ne fait ce calcul à l’avance. La question surgit le matin où la facture arrive, ou l’après-midi où une longue conversation commence à renvoyer des erreurs de fenêtre de contexte à de vrais utilisateurs, et soudain « combien de tokens cela représente-t-il ? » devient la seule question qui compte. Le problème, c’est qu’un token n’est pas un mot, que le décompte dépend du modèle, et que la moitié de ce qui vous est facturé n’apparaît jamais dans la chaîne de votre prompt.
Cet article vous donne la méthode reproductible : quand une estimation approximative suffit, comment obtenir un décompte exact selon le fournisseur, ce qui est réellement facturé, et comment transformer des décomptes en projection de coûts qui résiste à un changement de tarifs.
Points clés à retenir
- Comptez les tokens avec le tokenizer du modèle que vous appelez : tiktoken pour OpenAI,
messages.countTokenspour Claude,countTokenspour Gemini, et le tokenizer Hugging Face propre au modèle pour Llama. - Les heuristiques du type caractères ÷ 4 sont acceptables pour la planification de capacité, mais jamais pour la facturation ; elles s’effondrent sur du code, du JSON, du texte non anglophone et les emoji.
- Le prompt facturé correspond à l’intégralité du corps de la requête, y compris le system prompt, le cadrage des rôles, les schémas d’outils et l’historique de conversation renvoyé, et non uniquement au message de l’utilisateur.
- Les décomptes de tokens en entrée sont déterministes, ceux en sortie ne le sont pas : échantillonnez 50 à 200 requêtes réelles, planifiez le coût à partir de la longueur moyenne des sorties et fixez
max_tokensà partir du p95. - Le coût estimé par requête est (input_tokens ÷ 1M) × input_rate + (output_tokens ÷ 1M) × output_rate, avec des tarifs relevés en direct sur la page de tarification du fournisseur.
Pourquoi un token n’est-il pas un mot ?
Un token est une unité de texte spécifique à un modèle, produite par un tokenizer en sous-mots, et il ne correspond ni à un mot ni à un caractère. Les tokenizers fondés sur le byte pair encoding, comme tiktoken d’OpenAI, fusionnent les séquences de caractères fréquentes en un seul token et découpent les mots rares en plusieurs morceaux. Le mot « idempotency » se code en quatre tokens (« id », « emp », « ot », « ency ») avec cl100k_base, l’encodage de l’ère GPT-4, et en trois (« id », « empot », « ency ») avec o200k_base, l’encodage utilisé par les modèles OpenAI actuels.
C’est ce dernier point qui compte pour la facturation : le découpage est propre au modèle. La même phrase produit des décomptes différents selon les tokenizers GPT, Claude, Gemini et Llama, parce que chacun a été entraîné sur des données différentes avec un vocabulaire différent. Tout décompte obtenu avec le mauvais tokenizer relève de la devinette.
Quand une estimation approximative suffit-elle ?
Pour de la prose en anglais, caractères ÷ 4 ou mots × 1,33 vous approche suffisamment pour dimensionner une colonne de base de données ou esquisser un plan de capacité. Utilisez les heuristiques pour la planification de capacité, jamais pour la facturation ni pour les décisions liées à la fenêtre de contexte.
Ces heuristiques échouent précisément là où se situe le trafic de production : code, JSON, texte non anglophone et emoji. Les charges utiles structurées se tokenisent selon des motifs de ponctuation et d’espaces que le décompte de caractères ignore, et un seul emoji peut se développer en plusieurs tokens : caractères ÷ 4 sous-estime donc fortement les chaînes riches en emoji. Les écarts entre tokenizers, modestes sur de la prose anglaise, deviennent nettement plus importants sur du code et des données structurées, c’est-à-dire exactement le type de contenu qu’envoie un résumeur ou un agent.
Quel compteur de tokens LLM donne un décompte exact ?
Le principe tient en une ligne : comptez avec le tokenizer qui appartient au modèle que vous appelez. Les routes par fournisseur :
| Fournisseur | Méthode de décompte exact |
|---|---|
| OpenAI | tiktoken, ou js-tiktoken dans Node et les runtimes edge |
| Anthropic | l’endpoint count-tokens, client.messages.countTokens() dans le SDK TypeScript |
| Gemini | ai.models.countTokens() dans le SDK @google/genai |
| Llama et autres modèles ouverts | le tokenizer propre au modèle, publié sur Hugging Face |
En JavaScript, js-tiktoken est un portage en JS pur : il n’y a donc aucun binaire WASM à charger ni mémoire à libérer manuellement, et vous pouvez importer un seul encodage plutôt que l’ensemble complet, ce qui garde le bundle léger :
import { Tiktoken } from "js-tiktoken/lite";
import o200k_base from "js-tiktoken/ranks/o200k_base";
const enc = new Tiktoken(o200k_base);
const count = enc.encode("Summarise this ticket thread for support.").length;
L’endpoint d’Anthropic est gratuit à appeler, soumis uniquement à ses propres limites de débit : il n’y a donc aucun argument de coût pour approximer les décomptes Claude avec le tokenizer d’un autre fournisseur. Considérez son résultat comme le décompte de référence avant l’appel, et non comme un décompte exact : Anthropic le documente comme une estimation, et le chiffre facturé provient des champs usage de la réponse. Les tokenizers évoluent aussi d’une génération de modèles à l’autre chez un même fournisseur. La documentation d’Anthropic sur le décompte de tokens indique que Claude 4.7 et les versions ultérieures reposent sur un tokenizer plus récent qui transforme le même texte en environ 30 % de tokens supplémentaires par rapport aux modèles Claude précédents, l’écart exact dépendant de votre contenu. Un ancien décompte n’est pas transposable ; refaites-en un sur le modèle que vous appelez réellement. Et lorsque vous voulez simplement le chiffre sans câbler un SDK, collez le prompt dans un compteur de tokens LLM qui couvre GPT, Claude, Gemini et Llama.
Pourquoi mon décompte ne correspond-il pas à la facture ?
Le prompt facturé correspond à l’intégralité du corps de la requête, pas à la chaîne que vous avez rédigée. Le cadrage des rôles, le system prompt, les schémas d’outils et de fonctions, ainsi que les séparateurs entre messages ajoutent tous des tokens : c’est pourquoi compter uniquement le message de l’utilisateur sous-estime systématiquement le total. Une seule définition d’outil peut ajouter des centaines de tokens en entrée à chaque requête qui la transporte.
L’historique de conversation est le multiplicateur. Une fonctionnalité de chat renvoie tout l’historique à chaque tour, si bien que l’entrée de chaque tour inclut tous les tours précédents, et le coût par conversation croît de façon superlinéaire avec la longueur de la conversation. La correction, côté décompte, est simple : assemblez exactement le tableau de messages, le system prompt et les outils que vous allez envoyer, et comptez cet ensemble. L’endpoint count-tokens d’Anthropic accepte la même charge utile que celle que vous auriez envoyée pour créer le message, définitions d’outils comprises : vous pouvez donc lui transmettre directement la requête assemblée.
Comment transformer des décomptes de tokens en estimation de coût ?
Le coût estimé par requête tient en une ligne d’arithmétique, gardée symbolique :
cost = (input_tokens / 1_000_000) * input_rate + (output_tokens / 1_000_000) * output_rate
Lorsque les fournisseurs prennent en charge la mise en cache des prompts, les tokens d’entrée mis en cache sont facturés à un cached_input_rate distinct et inférieur. Les prix par modèle changent en quelques semaines : aucun tarif n’est donc indiqué ici. Traitez les tarifs comme une configuration injectée dans votre code, relevez les valeurs actuelles sur la page de tarification du fournisseur, et utilisez un calculateur de coûts LLM pour comparer les chiffres à jour entre modèles.
Deux réalités façonnent toute estimation. Premièrement, les tokens en sortie sont généralement facturés à un tarif nettement supérieur à celui des tokens en entrée chez les principaux fournisseurs : la longueur des réponses domine donc souvent le coût. Deuxièmement, les décomptes en entrée sont déterministes, alors que ceux en sortie ne le sont pas : la même requête donne toujours le même décompte en entrée, mais ce qui revient varie selon l’échantillonnage. Mesurez la sortie empiriquement. Exécutez 50 à 200 requêtes représentatives, planifiez le coût à partir de la longueur moyenne des sorties, et fixez max_tokens au 95e centile afin que les réponses légitimes ne soient pas tronquées tout en plafonnant les générations qui s’emballent.
Comment savoir si un prompt entre dans la fenêtre de contexte ?
Les tokens d’entrée plus les tokens de sortie attendus doivent tenir dans la fenêtre de contexte du modèle, sans quoi l’appel échoue purement et simplement ou la réponse est tronquée. La vérification préalable a sa place dans votre wrapper de requête : répartissez le budget de la fenêtre entre contexte système, historique de conversation et marge pour la sortie, comptez la requête assemblée, et élaguez l’historique avant l’envoi plutôt qu’après une erreur. Un vérificateur de fenêtre de contexte vous indique si un prompt donné tient dans un modèle donné, sans avoir à mémoriser des tailles de fenêtre qui changent à chaque version.
L’emplacement du wrapper importe, car un dépassement est visible par l’utilisateur : réponse tronquée ou erreur en cours de flux, et le réflexe de l’utilisateur est de réessayer — un bug de budget de tokens facture donc deux fois. Les session replays de fonctionnalités adossées à des LLM font apparaître précisément cette boucle de nouvelles tentatives, bien avant qu’elle ne se manifeste sur une facture examinée une fois par mois.
Que journaliser en production
La méthode est stable même si les prix ne le sont pas : comptez la requête assemblée avec le tokenizer propre au modèle appelé, échantillonnez du trafic réel pour connaître votre distribution de sorties, et conservez les tarifs sous forme de configuration que vous actualisez depuis les pages de tarification. Puis bouclez la boucle en production. Tous les grands fournisseurs renvoient les décomptes de tokens réels dans les champs usage de la réponse, comme usage.input_tokens chez Anthropic et usageMetadata chez Gemini, sachant que l’API Interactions plus récente de Gemini, encore en Beta, renvoie usage avec total_input_tokens et total_output_tokens. Journalisez-les par requête dès le premier jour ; les enregistrer est trivial, les reconstituer après l’arrivée d’une facture surprise ne l’est pas.
FAQ
Puis-je utiliser tiktoken pour compter les tokens des modèles Claude ou Gemini ?
Non. Le tokenizer de chaque fournisseur possède son propre vocabulaire : un décompte tiktoken n'est donc valable que pour les modèles OpenAI et peut diverger sensiblement sur la même entrée pour Claude ou Gemini. Utilisez l'endpoint count-tokens d'Anthropic, gratuit à appeler, pour Claude, la méthode countTokens du SDK @google/genai pour Gemini, et le tokenizer publié sur Hugging Face pour les modèles ouverts comme Llama.
Quelle est la différence entre les paquets npm tiktoken et js-tiktoken ?
tiktoken est un binding WASM : il charge un binaire compilé et exige d'appeler free() pour libérer la mémoire de l'encodeur une fois le travail terminé. js-tiktoken est un portage en JavaScript pur, avec des méthodes en camelCase (getEncoding, encodingForModel), sans binaire WASM ni gestion manuelle de la mémoire, ce qui en fait le choix le plus sûr pour les runtimes edge et serverless. Importer un seul fichier de rangs d'encodage maintient la taille de son bundle réduite.
Les réponses en streaming rapportent-elles toujours l'usage de tokens ?
Oui, mais pas par défaut partout. Pour l'API Chat Completions d'OpenAI, définissez stream_options avec include_usage à true et l'API diffuse un dernier chunk supplémentaire dont le champ usage couvre l'intégralité de la requête et dont le tableau choices est vide. Anthropic diffuse l'usage automatiquement : l'événement message_start transporte input_tokens et les événements message_delta transportent les output_tokens cumulés. Journalisez ces champs plutôt que de compter vous-même les chunks diffusés.
Quel encodage tiktoken utiliser pour quel modèle OpenAI ?
Utilisez o200k_base pour les modèles OpenAI actuels tels que gpt-4o et ultérieurs, et cl100k_base uniquement pour les modèles de l'ère GPT-4. Les deux encodages découpent le texte différemment : un décompte obtenu avec l'un n'est pas transposable à l'autre. À partir d'un identifiant de modèle, encodingForModel dans js-tiktoken sélectionne l'encodage correspondant à votre place, ce qui évite de figer le mauvais encodage à mesure que les modèles évoluent.