DevKitHub

Encoding & Conversion

Base64 to PDF — Decode Base64 to Any File, and Any File to Base64

Paste Base64 from an API response, a data: URI or an email attachment to see what file it is and download it: a PDF, a ZIP, a Word document or anything else. Or choose a file to get its Base64. Nothing leaves your browser.

1 line

File

Type
PDF 1.4 (application/pdf)
Sizefrom 788 characters
591 bytes
Pagesfrom the page tree
1
File name
document.pdf
Read as
Base64 (standard alphabet)

The file is only ever downloaded, never opened or previewed on this page, and it is saved exactly as decoded: nothing is repaired, decrypted or converted.

This tool runs entirely in your browser. Your input is never uploaded, stored or logged.

How it works

Base64 carries bytes and nothing else: no file name, no type, not even a sign that it is complete. So the decoder reads the decoded bytes to say what the file is, from the signatures in the WHATWG MIME Sniffing standard and those of other common formats. A PDF starts with %PDF- and its version, which in Base64 is always JVBERi0; a ZIP starts with PK, which is UEsDB. Formats built on ZIP are told apart by the names in the archive’s central directory, read without decompressing anything: [Content_Types].xml with a word/ folder is a .docx, a stored mimetype entry names an OpenDocument file or an EPUB, and AndroidManifest.xml makes an APK. Legacy .doc, .xls and .msg files are told apart by their OLE2 directory. An API that labels everything application/octet-stream, or a data: URI that claims image/png, still gets a download with the right extension, and the disagreement is pointed out.

For a PDF, the header gives the version, and a later /Version in the document catalog overrides it. The page count is the page tree’s own /Count. PDF 1.5 and later can keep that inside compressed object streams, so those are inflated to find it; if the page tree still cannot be found, the /Type /Page objects are counted and the number is marked approximate, and when the object streams are encrypted the count is reported as unknown. An /Encrypt entry in the trailer means the file is encrypted: the algorithm and the permissions it denies are read from the encryption dictionary, but whether a password is needed to open it cannot be told without trying one. A PDF with no %%EOF was cut off; JavaScript and attached files are flagged. The download is exactly the bytes decoded — nothing is repaired or decrypted — and nothing is previewed on the page; HTML and SVG are never rendered.

Base64 is accepted as it arrives: wrapped at 64 or 76 columns, in the URL-safe alphabet, without padding, as a JSON string with its quotes and \n escapes, or as a whole JSON response, where the longest Base64-looking value is used and a filename or contentType field beside it is honoured. A data: URI of any type, an email attachment pasted with its MIME headers, and a PEM block work too. A length one character past a group of four cannot come from any encoder, so it is reported as cut off; decoded bytes that are themselves Base64 text were encoded twice, and are offered for decoding again. Encoding gives the Base64 on one line or wrapped for PEM or MIME, a data URI, which is never wrapped, and a JSON string. Files up to 3.75 MB (5 MB as Base64) are accepted; anything over about 750 KB is processed in a background worker, so the page does not freeze.

Common problems

Every example below is run against this tool in our test suite, so what it says here is what the tool actually does.

Not valid Base64: the length is incomplete

JVBERi0xLjQK1
Why:
Base64 is written in groups of four characters, and a string one character past a whole group cannot come from any encoder. It was cut off — by a log line limit, a database column that is too short, a terminal or a clipboard.
Fix:
Copy the value again in full, from its source rather than from a log. A string cut at a group boundary does decode, and the PDF is then flagged as having no %%EOF.

That is the raw text of a PDF (it starts with %PDF-), not Base64.

%PDF-1.7
%âãÏÓ
1 0 obj
Why:
The value was never Base64, or had already been decoded and was then opened as text and copied. A PDF’s binary streams do not survive being copied as text, so it cannot simply be saved again.
Fix:
Get the file itself, or the Base64 value the API returned. In code, write the decoded bytes straight to a file instead of converting them to a string.

That is JSON, but none of its string values looks like Base64 or a data: URI.

{"status":"ok","documentId":"inv_0042","url":null}
Why:
The response refers to the document instead of containing it — an ID or a download URL — or the content has to be requested with a separate call or parameter.
Fix:
Find the call or parameter in the API’s documentation that returns the content, then paste that response, or the field on its own.

The PDF downloads but will not open: "There is no %%EOF marker".

Why:
The Base64 was cut at a multiple of four characters, so it decodes cleanly, but the end of the PDF — its cross-reference table and %%EOF — is missing. A VARCHAR column, a log line limit and a spreadsheet cell, which holds at most 32,767 characters, are the usual culprits.
Fix:
Take the value from its source, not from a log or a spreadsheet, and compare the Size shown here with the size the file should be.

The download is a .txt file full of Base64.

Why:
The file was Base64-encoded twice — often by a JSON serializer that encodes a byte array as Base64 by default, as System.Text.Json and Jackson do, when the bytes it was given were already Base64 text.
Fix:
Use Decode again, which appears when the decoded text is itself Base64 of a recognisable file. Then change the producer so it encodes only once.

The PDF asks for a password once it is downloaded.

Why:
It is encrypted: its trailer has an /Encrypt entry, shown in the warnings with the algorithm. Decoding Base64 cannot remove PDF encryption, so the download is the same encrypted file.
Fix:
Ask the sender for the password. Nothing that decodes Base64 can open it without one.

Frequently asked questions

How do I convert Base64 to PDF?
Paste the Base64 into Base64 → File. Type shows PDF and its version, Pages the page count, and Download .pdf saves the file. The Base64 can be on one line or wrapped, in a data: URI, or inside a JSON response.
How do I convert a PDF to Base64?
Switch to File → Base64 and choose the PDF. Copy the Base64 on one line for JSON and most APIs, at 76 characters a line for an email body (MIME), or at 64 for PEM. The data URI is always a single line.
Is my file uploaded anywhere?
No. Decoding and encoding both run in your browser, and the file and its Base64 are never sent to a server. Your browser’s network panel shows no request carrying them.
Why is there no preview of the PDF?
The file is only ever downloaded. Showing a PDF inside the page would need an embedded viewer, which this site’s Content Security Policy does not allow (object-src 'none'), and a file from an unknown source is better opened in your own viewer than inside a web page.
What does JVBERi0 mean?
It is %PDF- in Base64, so every PDF encoded as Base64 starts with it — JVBERi0x for a PDF 1.x. Others worth knowing: UEsDB is a ZIP, and so a .docx or .xlsx; iVBORw0KGgo is a PNG; /9j/ is a JPEG; H4sI is gzip.

Last updated