Skip to content
Skip to Content

Docs / Guides

Estimate cost before a run

Size a translation run before you spend: count the keys with a dry run, let verbatra turn them into requests, tokens and money, then cap the run you agreed to.

Use this before a first run on a real project, or before any run someone has to approve. verbatra publishes no prices, because rates belong to the provider and change without notice. It counts what you will be billed for, and turns that into money once you give it your provider's current rates.

For a typical project, the first run is the one that costs anything, and the next run costs almost nothing because only changed keys are sent.

Count the work

verbatra translate --dry-run
Output
verbatra translate (dry run)
  de: 400 would translate, 0 unchanged
  es: 400 would translate, 0 unchanged
  fr: 400 would translate, 0 unchanged
3 succeeded, 0 partial, 0 failed (dry run: nothing written)

would translate is the number of keys a real run would send: those missing from the target file plus those whose source text changed. A dry run constructs no provider, reads no key and writes nothing. Treat the count as an upper bound: it skips the cache, which serves repeat strings for free on a real run, and it does not merge identical source strings, which a real run sends once.

Estimate the spend

verbatra translate --estimate
Output
verbatra translate (estimate)
  de: 400 would translate, 0 unchanged
  es: 400 would translate, 0 unchanged
  fr: 400 would translate, 0 unchanged
  estimate: 1200 keys in 24 requests, ~40944 input + ~30720 output tokens
  estimated spend: no rate on file for gemini/gemini-2.5-flash; add rates.table["gemini/gemini-2.5-flash"] to your config to see a currency figure
  estimate excludes: cache hits, duplicate source strings, provider-side retries, translation length, tokenizer differences, repair requests
3 succeeded, 0 partial, 0 failed (dry run: nothing written)

--estimate implies --dry-run, so it spends nothing. It reports the unit your provider bills: tokens for an LLM, source characters for DeepL and Google Cloud Translation, and no API cost for a self-hosted openai-compatible or libretranslate server. With --json, the same figures sit under result.estimate per locale and in total, so a script can gate on them.

To see money, look up your model's current rate on the provider's own pricing page:

ProviderBilled byPricing
Geminiinput and output tokens (free tier available)Gemini API pricing
Anthropicinput and output tokensAnthropic pricing
OpenAIinput and output tokensOpenAI API pricing
OpenCodeinput and output tokensOpenCode Zen pricing
DeepLsource charactersDeepL API pricing
Google Cloud Translationsource charactersCloud Translation pricing
openai-compatible, LibreTranslatenothing: your own serverno API cost

Then add it to the config with the date you read it:

verbatra.config.ts
export default defineConfig({
  // ...
  rates: {
    asOf: "2026-01-15",
    currency: "USD",
    table: {
      // placeholders: copy the current rates from https://ai.google.dev/gemini-api/docs/pricing
      "gemini/gemini-2.5-flash": { inputPerMillionTokens: 1, outputPerMillionTokens: 2 },
    },
  },
});

The rates above are placeholders, not quoted prices. Every figure printed from them carries the asOf date, so an old rate card is visibly old. verbatra never invents a missing rate or prints 0.00 for a model it cannot price; it names the missing entry instead. See rates for the key format and units.

Know what the figure covers

The estimate performs the arithmetic you would otherwise do by hand:

  • Requests. Each locale's keys are split into batches of at most maxBatchSize (default 50), one request each, plus the batches generatePlurals would send.
  • Input. Every LLM request carries fixed system rules (about 550 tokens) and a response schema (about 100 tokens), then the keys, their descriptions, the tone, and the target locale's full glossary. The prompt is measured by serializing the payload that would be sent, so a large glossary is counted on every request it rides on.
  • Output. A translation does not exist yet, so it is sized as the source text plus 50 percent, since German, French and Russian often run a third to a half longer than English.
  • Tokens. Characters are converted at about four per token, which fits English prose; other scripts run denser.

A real run usually costs less, for the two reasons the dry-run count is an upper bound. It can also cost more, and the estimate excludes line names each way. Two matter most:

  • Retries. A failed request is retried: up to two extra attempts for Anthropic, OpenAI, OpenCode, openai-compatible and Gemini, five for DeepL, none for Google Cloud Translation and LibreTranslate. An attempt that reached the model is billed.
  • Repairs. When keys come back missing, verbatra sends one repair request, which carries the system rules, glossary and tone again in full.

Plan with the figure; do not promise it as a ceiling. The estimate also covers translate only: retranslating one entry from Studio or an agent tool spends on its own path.

Cap the run

Give the run you agreed to a hard stop a little above the estimate's input plus output tokens:

verbatra translate --max-tokens 80000

A request that would pass the ceiling is withheld rather than sent, and its keys stay pending for the next run. When the config also sets maxTokens, the lower figure applies. DeepL, Google Cloud Translation and LibreTranslate report no tokens, so the ceiling is enforced against verbatra's own projection for them. See Token ceiling, and maxTokens and budgetBehavior for a budget that applies to every run.

Calibrate on one locale

The precise number comes from a real run. Translate one locale and read the usage:

verbatra translate --locales de
Output
verbatra translate
  de: 400 translated, 0 unchanged, 18400 tokens (10800 in, 7600 out)
  total: 18400 tokens (10800 in, 7600 out)
1 succeeded, 0 partial, 0 failed

Multiply by the number of remaining locales. With --json, the figures are usage.inputTokens and usage.outputTokens. The run spends real money, but the work is kept: that locale is done.

Read what past runs costnew

Studio's Overview lists recorded runs with their cost, frozen when the run ended, so a later change to rates never rewrites it. An amount is the tokens the provider reported times the rate on file at that time. Estimated is a source-characters figure for a provider that reports no usage. At least is a lower bound, because a locale reported no tokens. No rate means no rate matched that model, and unknown means keys were sent but no tokens came back; neither is free. Self-hosted providers read not billed. The record is documented under runHistory; Review in Studio shows the page.

Machine-translation providers

DeepL and Google Cloud Translation bill source characters, not tokens, and LibreTranslate counts source characters without billing anything. verbatra sends them the source text with placeholders as short numbered markers, and no system rules, key names or JSON around it. The estimate counts source characters only. DeepL does not bill the tags around its markers; whether Google bills the span markup around them is not documented. A value these providers withhold (PLACEHOLDER_UNSUPPORTED) is not sent, so the characters sent can be fewer than the raw total.

Google Cloud Translation

Google Cloud Translation is counted like DeepL: source characters in the estimate, and a projected token figure for a maxTokens budget, marked as estimated on the run summary.

Estimate from an agent

Two agent tools return what translate --estimate --json prints, for all locales or a subset, and never call a provider:

ToolWhere
translation.estimatethe MCP server
verbatra_translation_estimateStudio's agent tools

Spend within the estimate

translation.translatePending then takes the same locales and a maxTokens ceiling. See Estimate, then spend.

Why the next run costs less

The figures above are the first-run cost. After that, verbatra sends only keys that are missing or whose source changed since the lock file baseline, and the cache reuses earlier translations of identical strings. Day to day you pay for the strings you edited. To rehearse for free, use Gemini's free tier or point openai-compatible at a local model; see Providers.

Edit on GitHub

On this page