Base45 encoder and decoder
AB becomes BB8 in Base45, the RFC 9285 encoding that keeps data within the 45 characters a QR code reads in alphanumeric mode, as EU Digital COVID Certificates do. Decoding turns Base45 back into text. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Text
- AB
- Calculation mode
- Encode
- Result
- BB8
- Encoding
- base45
- Input bytes
- 2
- Output bytes
- 3
This Base45 encoder converts plain text into RFC 9285 Base45 and decodes Base45 strings back to UTF-8 text using the forty-five character QR Code Alphanumeric alphabet. The scheme powers EU Digital COVID Certificates and other QR verifiable credentials that must carry binary claims without leaving the QR-safe character set. The engine is fully deterministic: the same input and mode always produce the same result, with no network calls, no random salts, and no date-dependent shortcuts. Classic checks include encoding AB to BB8, Hello!! to a string that includes a space, and base-45 to UJCLQE7W581.
What Base45 is and what this tool returns
Base45 is the binary-to-text encoding defined in RFC 9285 for data that will travel inside QR codes in Alphanumeric mode. The alphabet is the fixed forty-five character set zero through nine, A through Z, space, dollar, percent, asterisk, plus, minus, period, slash, and colon. Encoding interprets each pair of input bytes as a sixteen-bit unsigned integer n equals a times two hundred fifty-six plus b, then writes n as three base-forty-five digits with the least significant digit on the left.
A final leftover byte becomes two digits only. That design matches QR alphanumeric packing better than Base64, which needs plus, slash, and padding that are awkward in QR alphanumeric mode. This page always follows that contract: encode mode UTF-8 encodes your text, packs the bytes, and returns only alphabet characters; decode mode reverses the process and rejects non-alphabet characters, incomplete groups whose length mod three is one, and any three-character triplet whose numeric value exceeds sixty-five thousand five hundred thirty-five.
How text and mode are read and how results stay reproducible
Encode accepts any Unicode string, converts it with the platform TextEncoder to UTF-8 bytes, then emits Base45 groups as specified above. Decode requires a pure Base45 string: length mod three equal to one is rejected because it cannot represent a whole number of bytes, and any character outside the alphabet fails with a clear index and character. After digits are recovered, each triplet is checked against the sixteen-bit ceiling so strings such as GGW, which would decode above sixty-five thousand five hundred thirty-five, fail instead of overflowing.
Two-character tails must decode to a single byte at most two hundred fifty-five. A fatal UTF-8 decode then ensures binary garbage does not become mojibake text.
Where Base45 is used in QR codes
Frontend teams decode scanned Base45 segments during integration debugging without pasting data into ad-hoc scripts that accidentally use the wrong alphabet. Backend services encode short binary blobs before putting them in QR generators that only accept alphanumeric mode. Quality engineers generate deterministic encode and decode pairs for contract tests so a middleware that claims Base45 support cannot silently switch tables or accept oversized triplets.
Educators use the same tool when teaching how QR alphanumeric mode, fifteen-bit pairs of symbols, and Base45 interact, including the classic RFC examples AB to BB8 and Hello!! with its embedded space.
FAQ
What does the Base45 encoder cost?
It is free in your browser on this page.
How is Base45 different from Base64?
Base45 uses the 45-character QR Alphanumeric alphabet and packs two bytes into three characters. It has no padding and is designed for QR codes, not email or JWT segments.
What is an invalid Base45 triplet?
A three-character group whose value exceeds 65535 (for example GGW).
Is the result deterministic?
Yes. The same text and mode always produce the same result with no network, randomness, or date-dependent behavior.
Why does my Base45 result contain spaces?
Because the space is one of the 45 characters Base45 uses, alongside digits, capital letters and symbols such as $, %, * and +. Hello!! encodes to a string that includes a space, so copy the whole result, spaces included, before you decode it.
Related tools
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/enc/base45 \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"AB"}'const res = await fetch("https://api.kit.forhosting.com/enc/base45", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "AB"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/base45",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "AB"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/base45", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"AB"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"AB"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/base45", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "AB"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.base45",
"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.
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. |
Technical notes
Base45 packs two bytes into three characters and a leftover byte into two characters, which is more compact for QR payloads than Base64 while staying inside the alphanumeric mode scanners already expect. Use it free in the browser for credential debugging and teaching, or call the API at $0.002 per successful request when pipelines need reproducible Base45 transforms in CI and backend services.
What Base45 is and what this tool returns
The JSON response includes result for the transformed string, mode echoing encode or decode, encoding fixed to base45, and input_bytes plus output_bytes so you can assert sizes in tests. There is no streaming path and no silent fallback to Base64: either the string is valid Base45 text or the request fails with invalid_input. If you need standard Base64url for JWTs instead, use a dedicated Base64url endpoint; this landing is only for the RFC 9285 alphabet used by QR verifiable credentials.
How text and mode are read and how results stay reproducible
The preferred payload field is text, with aliases input, value, and s so forms, query strings, and SDK clients can reuse the same contract without renaming columns. Mode defaults to encode and accepts decode explicitly; aliases op, direction, and action map to the same switch for scripts that already use those names. Pair the free browser run on this page with the priced API when you need the identical mathematical result inside an automated pipeline without re-implementing Base45 tables yourself. Invalid inputs return invalid_input and are not charged, which keeps validation cheap while successful transforms remain a fixed item price of $0.002.
Where Base45 fits in QR credentials, APIs, and test fixtures
On this page the work runs entirely in your browser; through the API each successful lookup costs $0.002, failed validation is not charged, and nothing is stored after the response returns. That split — free interactive exploration and a priced, identical API — matches the rest of the KIT tier-A catalog and lets you move from a classroom demo to an automated pipeline without changing the encoded result. Pair it with CBOR or certificate helpers when you need related credential steps, and with other encoding endpoints when you are building a small lab of free, deterministic text tools.
Integration use cases
QR verifiable credentials
Encode or decode RFC 9285 Base45 payloads used by EU Digital COVID Certificates and other QR-borne verifiable credentials.
Alphanumeric QR fixtures
Turn short binary-safe text into Base45 so QR generators can use Alphanumeric mode without leaving the 45-character alphabet.
Deterministic CI fixtures
Generate reproducible Base45 strings for unit tests, golden files, and contract checks across wallet and scanner services.
Technical questions
What modes are supported?
mode=encode (default) turns plain text into Base45. mode=decode turns a Base45 string back into UTF-8 text.