QR Code Version Calculator
This QR code version calculator estimates the smallest symbol that can hold a specified number of bytes at error-correction level L, M, Q, or H.
Run — free
It uses the standard byte-mode capacity limits for QR versions 1 through 40, then reports the selected version, physical module count, available capacity, and unused bytes. The result helps you size a QR code before generating artwork, choosing print dimensions, or deciding whether stronger error correction will make the symbol too dense.
Start with the encoded byte length
QR capacity depends on the encoding mode, not merely on how many characters a person sees. This calculator deliberately uses byte mode because it is the dependable general-purpose choice for URLs, prose, identifiers, and mixed punctuation. Enter the number of bytes that your final payload occupies after text encoding. Plain ASCII usually consumes one byte per character, while accented letters, emoji, and many non-Latin scripts consume more than one byte in UTF-8. If you only count visible characters, you may select a version that is too small. Include every character that will actually be encoded, including URL query strings, separators, line breaks, and structured-data prefixes. The result names the first QR version whose byte-mode limit is at least that length. It also shows remaining bytes, which provides a useful buffer when the payload might grow before production. This estimate does not optimize numeric or alphanumeric content into their more compact QR modes, so a specialized encoder may fit eligible data into a smaller symbol.
Choose an error-correction level intentionally
Error correction trades capacity for resilience. Level L retains the most room for data and is suitable when the code will be displayed cleanly and scanned under controlled conditions. Level M is a common general-purpose choice. Levels Q and H reserve progressively more codewords for recovery, which can help when labels may be scratched, packaging may curve, or a design places a small obstruction near the code. That protection makes the required version rise sooner for the same payload. Run the same byte length at several levels to see the size consequence before committing to artwork. A higher level is not automatically better: increasing the version creates more modules, and those modules become physically smaller if the printed area stays fixed. Very small modules can reduce scanning reliability even though the symbol contains stronger error correction. Choose the lowest level that reasonably matches the expected damage, surface, contrast, viewing distance, and printing process, then preserve a proper quiet zone around the finished code.
Interpret version and module dimensions
QR versions run from 1 through 40. Version 1 has 21 modules on each side, and every following version adds four modules per side. The reported modules-per-side value therefore describes the square data grid, not its final size in millimetres or pixels. A generator must still add the quiet zone, commonly four modules on every edge, and each module needs enough physical size for the target camera and distance. The minimum version is a capacity result rather than a complete scan-quality guarantee. Actual encoder output can differ if software automatically switches between numeric, alphanumeric, byte, or Kanji segments, adds an explicit character-set marker, or uses nonstandard structured append behavior. Treat this result as a conservative byte-mode planning figure and confirm the final generated symbol with the exact encoder and payload you will ship. If the calculator rejects the input, version 40 cannot hold that many byte-mode bytes at the chosen correction level; shorten the payload, lower the correction level, or encode a compact reference instead.
What you can do with it
Plan printed labels
Estimate symbol density before reserving space for a QR code on packaging, tickets, or equipment labels.
Compare correction levels
See how moving from M to Q or H changes the minimum version for the same byte payload.
Validate payload budgets
Set a byte limit for generated URLs or structured records before sending them to a QR encoder.
FAQ
What does data length mean?
It is the number of bytes in the final payload, not necessarily the number of visible characters.
Which QR encoding mode does this use?
It uses byte mode. Numeric or alphanumeric mode can hold more eligible characters than the byte-mode estimate.
What do L, M, Q, and H mean?
They are the four QR error-correction levels, ordered from greater data capacity to greater recovery capability.
Does the result include the quiet zone?
No. Modules per side describes the QR symbol grid. Add the quiet zone required by your generator and printing specification.
Why might my QR generator choose another version?
It may segment the payload into more efficient modes or add metadata such as a character-set designator. Confirm final output with the encoder you will use.
What does an API request cost?
Each API request costs $0.002. The browser version runs locally for free.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/doc/qr-code-capacity-estimate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"data_length":100,"error_correction_level":"M"}'const res = await fetch("https://api.kit.forhosting.com/doc/qr-code-capacity-estimate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"data_length": 100,
"error_correction_level": "M"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/doc/qr-code-capacity-estimate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"data_length": 100,
"error_correction_level": "M"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/doc/qr-code-capacity-estimate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"data_length":100,"error_correction_level":"M"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"data_length":100,"error_correction_level":"M"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/doc/qr-code-capacity-estimate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"data_length": 100,
"error_correction_level": "M"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "doc.qr_code_capacity_estimate",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |