DEV Community

OnePassApps
OnePassApps

Posted on

Decode Base64 in Your Browser: The Two Errors the Text Studio Reports, and the One It Never Mentions

I work on OnePassApps. This is the Text Studio's Base64 tab again, but this time I drove the decode side of it and wrote down what it refuses, what it quietly shortens, and what happens to a result you have already used.

The earlier post on this tab covered the encode side - the UTF-8 byte count, the = padding and the round trip you can check yourself. If you have not read it, it is here: Base64 in the Browser: UTF-8 Bytes, Padding and a Round Trip You Can Check. This one is about the decode path, and it is a different set of facts.

Open the tool here: the Text Studio

Every line below was read off our own build in a browser on 8 November 2026, with the tab open and the panel in front of me. Nothing here is a spec sheet.

The decode side renames its own parts

The Text Studio carries eight tabs on one page - Clean, Case, Duplicate lines, Sort lines, Find & replace, Diff, Markdown, Base64 - and the page line over them reads "Count, clean, compare and convert text locally. Your content stays in this browser tab."

Switch the Mode radio to Decode Base64 and the panel relabels itself. The first step is no longer "01 Input text" but "01 Base64 input". The result step's hint changes with it, from "Base64 text shows on the stage, ready to copy, download or use as the new input." to "Decoded text shows on the stage, ready to copy, download or use as the new input." The action button becomes Decode, and the page keeps saying "Nothing leaves this tab."

The stats row under the input still counts the input, not the output, so it counts the Base64 string. A 52-character Base64 string reads Words 1, Characters 52, Sentences 0, Lines 1, UTF-8 bytes 52 - the Base64 alphabet has no spaces, so the sentence counter has nothing to count.

A round trip, measured in the tab

I typed OnePassApps works in the browser tab. into the input - 37 characters, 6 words, 1 sentence, 37 UTF-8 bytes - and pressed Encode. The stage answered "Encoded in 0.1 s" and printed "52 characters · 1 line", with the value:

T25lUGFzc0FwcHMgd29ya3MgaW4gdGhlIGJyb3dzZXIgdGFiLg==
Enter fullscreen mode Exit fullscreen mode

I checked that string outside the browser against Python's own base64 module over the same UTF-8 bytes, and it agreed character for character. Pasting it back and pressing Decode gave the sentence back exactly - "37 characters · 1 line", "Decoded in 0.3 s" in that run and "Decoded in 0.1 s" in another, and the stage labels the work "Base64 decoded as UTF-8 text."

It refuses bad input, and it says which kind of bad

Paste something that is not Base64 - I used not base64!! - and the stage answers:

Invalid Base64: use standard Base64 characters and correct padding.

followed by "Nothing was changed. Fix the problem and try again." The result block reads "No new result". Nothing half-decoded, no garbage characters, and the input is left exactly as you typed it.

There is a second refusal, and it is the one I did not expect. The string //79 is perfectly good Base64 - it decodes to three bytes - but those bytes are not valid UTF-8, and the panel answers:

Invalid Base64: decoded bytes are not valid UTF-8 text.

Same second line, "Nothing was changed. Fix the problem and try again." The wording is worth reading carefully: the Base64 was valid, the UTF-8 was not, and the tool calls both cases "Invalid Base64". It is refusing rather than handing you replacement characters, which is the behaviour you want - a mangled byte string would look like a decode that worked.

A short string decodes to short text, without a word of complaint

Here is the edge I would not have predicted. I cut the encoded string down to its first 48 characters - a whole number of Base64 groups, with no padding at all - and pressed Decode. No error, no warning: the stage said "Decoded in 0.1 s", printed "36 characters · 1 line", and gave back:

OnePassApps works in the browser tab
Enter fullscreen mode Exit fullscreen mode

The full stop is gone, because the characters that covered it are the ones I removed. The tool is not wrong - 48 Base64 characters really do describe 36 bytes - and that is exactly what it returned. But the stage gave no hint that the string described less text than the one I had copied, so a truncated Base64 string will not tell you that it is truncated. If the decode is going somewhere important, check the character count the stage prints against the length you expected.

A newline inside the string is a different matter: I broke the same 52-character string across two lines, and it decoded to the full 37 characters with the full stop intact. Whitespace in the middle is ignored; a missing tail is not flagged.

The result goes out of date, and says so

The stage offers three ways out: Copy, Download .txt, and "Use as input", which feeds the decoded text back into the input box so you can run it straight into the next tool.

I pressed "Use as input" after a successful decode. The input box took the decoded sentence - the counter changed to "37 / 2,000,000", and Words 6, Characters 37, Sentences 1, Lines 1, UTF-8 bytes 37 - and the result block then read:

Out of date

followed by "Input changed. Run Decode again for a new result." and the action button went back to "Decode".

So the tool does not leave a stale answer sitting on the stage looking current. The moment the input changes, the old result is marked as out of date and the panel tells you what to do about it.

Nothing was uploaded

I traced the network for the whole decode session with the browser's own request log: 94 requests, none of them a POST or a PUT, and not one request carried a body. The text went into a text field and came back out as text.

The limits of this measurement

One build, one browser, one signed-out session, 8 November 2026. The input was typed and pasted as text, so the file-picker path was not exercised in this run. In encode mode on the same tab the panel offers ".txt, .md, .csv and other text up to 8 MiB", and in decode mode the input counter still reads against a 2,000,000-character limit. I did not test Base64url, line-wrapped blocks wider than one line, or a payload that decodes to text with a byte-order mark, and I did not test what happens when the decoded text is longer than the input limit it has to go back into.

The studios run on the OnePassApps membership, and the page is explicit about what that costs right now: "Standard is free right now", "$0 / month", "100,000 credits every 30 days · No end date set · No card required", and "No automatic paid subscription. Existing paid subscriptions keep their terms."

Every studio has a plain-language guide with the limits and the tool list: the OnePassApps guides

I work on OnePassApps - the Text Studio is one of nine apps on a single membership, and every one of these tools runs in the tab.

Top comments (0)