Repair Base64 Strings Your Decoder Rejects

Paste a Base64 value throwing "Incorrect padding" or "Invalid character" errors. The page strips line breaks, headers, quotes, stray characters, restores padding, then decodes the result so you see the real bytes before shipping them.

Try a broken sample:
0 charsRepairs as you type
Waiting for input0 chars ยท Ctrl+Enter copies

Fixes to apply

Repair steps, run in this order

What changed

    Decoded check

    Size
    -
    Looks like
    -

    Decoded bytes show up here.

    Match your error message to the fix

    Every runtime words a Base64 failure differently. Find your error in the left column. The middle column names the usual cause, the right column names the switch above for the job.

    Error you gotUsual causeSwitch on this page
    Browser atob(): InvalidCharacterErrorA data: header, wrapping quotes, or -_ from a JWT. Line breaks pass, atob() skips whitespace.Headers, prefixes. URL-safe alphabet.
    Python: binascii.Error: Incorrect paddingTrailing = dropped by a URL, cookie, or JWTPadding
    Java: Illegal base64 character 20Hex 20 is a space. A + went through a query string parser and came out as a space.Spaces were + signs
    Go: illegal base64 data at input byte 0The byte at the reported offset sits outside the alphabet. Offset 0 usually means a quote. Go skips \r and \n on its own, so spaces, backslashes, or - from base64url are the usual suspects.Quotes, JSON escapes. URL-safe alphabet.
    PHP: base64_decode($s, true) returns falseSame causes as Go. Without strict mode PHP skips junk silently and hands back shifted bytes.Characters outside the alphabet
    No error, broken image or garbled textAn = in the middle from two joined strings, or a cut-off tailPadding mid-string. Read the truncation warning.

    The sample on this page, step by step

    Click Wrapped email body above. The string is a usage invoice for toolexe.com, copied out of a raw email. Mail clients wrap Base64 at 76 characters. This copy also picked up four spaces of indent per line. The == at the end got lost too.

    1. The log reports 2 line breaks plus 12 spaces removed. Three lines, four spaces each.
    2. 214 characters remain. 214 divided by 4 leaves 2, so 2 padding characters go on the end.
    3. The decoded check reads 160 bytes of UTF-8 text and prints the invoice, ending with Wajahat Qasim's billing address.

    Next, click + lost in a URL. The string decodes without any error, but into 30 bytes of noise. The blue hint explains why. One click on Treat spaces as + signs brings back the 32-byte HMAC-SHA256 reset token. Most fixers strip those spaces and stop, which hands you a decodable, wrong value.

    Why the fixes run in a fixed order

    The checklist runs top to bottom. Two pairs only work in sequence:

    After cleanup, the page decodes to bytes and encodes those bytes again. The output is canonical: the same bytes always give the same string. The output menu picks the flavor. Use URL-safe without padding for JWT segments, MIME for email bodies, PEM for certificates and keys.

    How the page spots a cut-off string

    Padding makes a truncated string decodable. The missing bytes stay missing. To catch this, the page reads the leftover bits in the last character. Every clean encoder sets those bits to zero. Nonzero bits mean the string stopped partway through a byte group, and the log raises a warning.

    The check catches about two cut-offs in three. When the cut lands on a 4-character boundary the bits look clean. Only the content gives the problem away: JSON missing its closing brace, a PNG missing its IEND chunk, a gzip stream failing its CRC. Load Cut-off payload to see both warnings fire on one string.

    The same repair in your own code

    Once the log names the cause, fix the producer. Where a decoder has to tolerate the damage, these handle padding plus the URL-safe alphabet.

    Browser JavaScriptconst fix = s => {s = s.replace(/\s+/g, '').replace(/-/g, '+').replace(/_/g, '/');return s + '='.repeat((4 - s.length % 4) % 4);};const bytes = Uint8Array.from(atob(fix(input)), c => c.charCodeAt(0));
    Pythonimport base64, re
    s = re.sub(r'\s+', '', s)data = base64.urlsafe_b64decode(s + '=' * (-len(s) % 4))
    PHP$s = strtr(preg_replace('/\s+/', '', $s), '-_', '+/');$bytes = base64_decode($s . str_repeat('=', (4 - strlen($s) % 4) % 4), true);
    Gos = strings.TrimRight(strings.NewReplacer("+", "-", "/", "_").Replace(s), "=")b, err := base64.RawURLEncoding.DecodeString(s)
    Watch out for lenient decoders. Node's Buffer.from(s, 'base64') and Python's b64decode() without validate=True both skip characters outside the alphabet with no error. Feed them dG9v*bGV4ZQ and you get toolexe back. Convenient, until a stray character in binary data shifts every byte after it. Validate first when the bytes matter.

    When repair is the wrong move

    Nothing you paste leaves your browser. Repair, decoding, file type detection, previews all run in JavaScript on this page, so no server sees a token or key you test here.

    Base64 repair questions from developers

    Padding math, URL-safe strings, truncation, framework quirks.

    How do I fix "Incorrect padding" in Base64?

    Add = signs until the length divides by 4. A length of 4n+2 needs two, 4n+3 needs one. A length of 4n+1 has no valid padding, since one character is extra or three went missing. The Padding switch on this page handles all three cases and flags the last one.

    Why does my Base64 have spaces where + signs belong?

    Query strings and HTML forms encode a space as +, so the server decodes every + back into a space. When a Base64 value goes into a URL without encodeURIComponent, each + arrives as a space. Turn on "Spaces were + signs" to restore the original, then fix the sender by percent-encoding the value.

    What is the difference between Base64 and base64url?

    base64url, defined in RFC 4648 section 5, swaps + for - and / for _ so the value survives URLs and file names. Most producers also drop the = padding. JWTs use base64url for all three segments, which is why a JWT segment fails in atob() until converted.

    Does repair bring back a truncated Base64 string?

    No. Padding makes the string decode, but bytes past the cut are gone. The page warns when the last character carries leftover bits, which catches about two cut-offs in three. Re-export the value from its source.

    Why is the output different from what I pasted beyond the fixes listed?

    The page decodes to bytes and encodes them again, so the output is canonical. Leftover bits in the last character get zeroed. Line wrapping follows the output format you picked. The decoded bytes stay identical.

    Why does a Laravel APP_KEY start with "base64:"?

    Laravel tags keys stored as Base64 with a base64: prefix so the framework decodes them before use. Strip the prefix before decoding anywhere else. The default AES-256-CBC key decodes to exactly 32 bytes in the decoded check.

    Is the string I paste sent to a server?

    No. Repair, decoding, previews run in your browser. Close the tab and nothing remains.