Base64 encoding turns any data into a limited set of 64 safe text characters, URL encoding makes text safe to place inside a web address, and JSON is a plain text format for structured data. They solve three different problems, and mixing them up is behind many confusing bugs. This guide explains what each one is, how it works, when to use it, and which errors show up most often, with examples whose outputs were computed with Python.
What is JSON and how does it work?
JSON (JavaScript Object Notation) is a text format for structured data made of objects, arrays, strings, numbers, booleans and null. It is the default way most web APIs send and receive data because it is easy for people to read and for programs to parse.
An object is a set of key and value pairs in curly braces. An array is an ordered list in square brackets. Keys must be strings in double quotes. Python’s json.dumps turned a small dictionary into this single line:
{“name”: “Ana”, “age”: 30, “tags”: [“a”, “b”], “ok”: true, “x”: null}
Notice that Python’s True and None became true and null. JSON has its own spellings, and they are lowercase. With indent=2 the same data is spread over several lines, which is easier to read but means exactly the same thing. If you paste a minified response into the JSON Formatter and press the button, it shows the structure indented, and it will also report where the text is invalid.
JSON strings can contain any Unicode character. Many tools write non-ASCII characters as escapes. For the word “café”, json.dumps produced "café" by default, and "café" when called with ensure_ascii=False. Both decode to the same text.
The official description of the format is on json.org, and the formal standard is RFC 8259.
What is Base64 encoding?
Base64 encoding is a way to represent binary data using only 64 printable characters: A to Z, a to z, 0 to 9, plus + and /, with = used for padding. It exists so that bytes can travel through systems built only for text, such as email bodies, JSON fields or HTML attributes. It is defined in RFC 4648.
It is an encoding, not encryption. Anyone can reverse it instantly, and it provides no secrecy at all. Treat it as a packaging format only.
How the conversion works
Base64 reads the input three bytes (24 bits) at a time and splits those 24 bits into four groups of 6 bits. Each 6-bit group is a number from 0 to 63 that maps to one character in the alphabet. That is why the output is always about one third larger than the input.
When the input length is not a multiple of three, padding fills the gap. Python gave these results:
| Input bytes | Base64 output | Note |
|---|---|---|
| Man | TWFu | 3 bytes, no padding |
| Ma | TWE= | 2 bytes, one padding character |
| M | TQ== | 1 byte, two padding characters |
| Hello, World! | SGVsbG8sIFdvcmxkIQ== | 13 bytes |
| café (UTF-8) | Y2Fmw6k= | 5 bytes, because é takes 2 |
The last row matters. Base64 works on bytes, not on letters. Text must first be turned into bytes with an encoding such as UTF-8, and the “é” becomes two bytes before Base64 sees it. You can try this yourself with the Base64 Encoder Decoder, which runs in your browser and shows the result after you press the button.
A size check: 300 zero bytes encoded to 400 characters, which matches the rule that every 3 input bytes become 4 output characters.
The URL-safe variant
Standard Base64 uses + and /, which both have special meaning in URLs. The URL-safe alphabet from the same RFC replaces them with - and _. For the three bytes 251, 255, 254, standard Base64 gave +//+ while the URL-safe version gave -__-. Web tokens and many APIs use the URL-safe form, often with the trailing padding removed.
What is URL encoding (percent encoding)?
URL encoding, also called percent encoding, replaces characters that are not allowed or have special meaning in a URL with a percent sign followed by two hexadecimal digits. A space becomes %20, for example. The rules are in RFC 3986.
Non-ASCII characters are first converted to UTF-8 bytes, and each byte is then percent encoded. Python’s urllib.parse.quote turned the text a b&c=d/é? into two different results depending on settings:
- Default settings:
a%20b%26c%3Dd/%C3%A9%3F. The slash was left alone becausequotetreats it as safe by default. - With
safe="":a%20b%26c%3Dd%2F%C3%A9%3F. Now the slash is encoded too.
The “é” became %C3%A9, which are its two UTF-8 bytes in hex. In HTML form submissions, a space is traditionally written as + instead. Python’s quote_plus gave a+b for “a b”. Use the URL Encoder Decoder when you need to check what a query value looks like before putting it in a link.
The key idea is to encode each value separately and before joining the parts. If a search term contains & or = and you do not encode it, the server will read it as a separator and split your value in two.
How are HTML entities different?
HTML entities are a third kind of escaping, used inside web page markup rather than inside URLs. They replace characters that HTML would treat as code, such as <, >, & and quotes, with named or numeric references. Python’s html.escape turned <a href="x">Tom & Jerry</a> into:
<a href="x">Tom & Jerry</a>
This is what prevents user-supplied text from being run as markup. The HTML Entity Encoder Decoder converts in both directions. The definitive list of named references is in the HTML Standard.
JSON, Base64, URL encoding and HTML entities compared
Each one protects data in a different place, so the right choice depends on where the data is going. This table summarizes the differences.
| Format | Purpose | Reversible? | Typical place | Size effect |
|---|---|---|---|---|
| JSON | Structure data as text | Yes | API requests and responses, config files | Adds punctuation |
| Base64 | Carry bytes as text | Yes | Email attachments, data URIs, tokens | About 33 percent larger |
| URL encoding | Make text safe in a URL | Yes | Query strings, path segments | Up to 3 characters per byte |
| HTML entities | Show markup characters as text | Yes | Web page content | Few extra characters |
None of these is a security feature on its own. They are formats for moving and displaying data correctly.
When should you use each one?
Use JSON when two programs exchange structured data. Use Base64 when you must put binary data, such as an image or a file, into a text-only channel. Use URL encoding for any value placed in a link, and HTML entities for any untrusted text shown on a web page.
Here is how they often combine in real work. An API sends a JSON object. One field holds a small image as Base64. That same JSON may be placed in a query parameter, so the whole string is URL encoded. Each layer is applied in order on the way out and removed in reverse order on the way in.
A few practical rules help:
- Do not Base64 encode large files into JSON if you can send them as a normal upload, because of the size increase.
- For small images in CSS or HTML, the Image to Base64 Converter produces a data URI, but each embedded image is bigger than the original file.
- HTTP Basic authentication uses Base64 for the “user:password” pair. Python gave
dXNlcjpwYXNzforuser:pass. That is trivially reversible, so it is only acceptable over HTTPS. - Never use Base64 to hide secrets such as keys or passwords.
More utilities of this kind are listed among our free tools.
What are the most common errors?
Most failures come from applying the wrong encoding, encoding twice, or ignoring character sets. The sections below cover the usual suspects.
JSON errors
- Trailing commas. A comma after the last item is invalid in JSON, even though many programming languages allow it.
- Single quotes. Keys and strings need double quotes.
- Comments. The JSON standard has no comment syntax.
- Unescaped characters. Raw line breaks and unescaped double quotes inside a string break parsing.
- Wrong value spelling. Use
true,falseandnullin lowercase.
Base64 errors
- Incorrect padding. Stripped or missing
=characters make some decoders fail. Add them back until the length is a multiple of four. - Mixing alphabets. Decoding a URL-safe string with a standard decoder, or the reverse, gives errors or wrong bytes.
- Wrong text encoding. Encoding “café” as Latin-1 on one side and decoding as UTF-8 on the other garbles the “é”.
- Line breaks and spaces. Some systems wrap Base64 at fixed line lengths, and a strict decoder may reject them.
- Thinking it is secure. It is not, as covered above.
URL encoding errors
- Double encoding. Encoding an already encoded string turns
%20into%2520. - Encoding the whole URL. This breaks the colons and slashes that make the address work. Encode the individual values instead.
- Plus versus %20. A
+means a space only in form-style query strings, not necessarily in paths. - Forgetting reserved characters. Unencoded
&,#and?in a value end up changing how the URL is read.
HTML entity errors
- Escaping in the wrong place. Escaping text twice shows literal
&on the page. - Using entities for URLs. A link target needs URL encoding, not entity encoding, although an
&in an HTML attribute should still be written as&in the markup.
How can you check your work step by step?
Decode in the reverse order you encoded, one layer at a time, and compare with the original. If a value arrives corrupted, look at the intermediate form after each step instead of guessing.
- Pretty print the JSON to see whether it is valid and which field holds the odd value.
- If the field looks like random letters ending in
=, try Base64 decoding it. - If you see many
%signs, URL decode first, then continue. - If you see
&or<patterns, decode HTML entities. - Confirm the result is valid UTF-8 text, or recognize it as binary, such as an image header.
A tiny example of a hash for comparison: Python’s SHA-256 of “hello” is 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824. Hashes are one way and look similar in hex form, but unlike Base64 they cannot be decoded. Do not confuse the two.
Frequently asked questions
Is Base64 encoding the same as encryption?
No. Base64 is reversible by anyone without a key, so it protects nothing. Use real encryption, such as TLS for transport, when data must stay private.
Why does Base64 make data bigger?
Every 3 bytes become 4 characters, so the output is about 33 percent larger, plus a little padding. In the Python check, 300 bytes became 400 characters.
Why does a Base64 string end with equals signs?
The equals signs are padding. They fill the output to a multiple of four characters when the input is not a multiple of three bytes. One input byte gives two padding characters and two input bytes give one.
Should I URL encode the entire link?
No. Encode only the parts that carry data, such as each query value or path segment. Encoding the whole link would also encode the separators that make it a valid URL.
Can JSON contain binary data?
Not directly. JSON is text, so binary data is usually Base64 encoded into a string field, or sent separately as a file upload.
What is the difference between URL encoding and HTML encoding?
URL encoding uses percent signs and makes text safe inside web addresses. HTML encoding uses entities like < and makes text safe inside page markup. They apply to different contexts and are not interchangeable.
Key takeaways
Pick the format by destination: JSON for structure, Base64 for bytes in text channels, percent encoding for URLs and entities for HTML. Apply each once, in order, and reverse it in the opposite order. When something looks wrong, decode one layer at a time and check the character set.
Free Tools Mentioned in This Guide
See all of them on the free online tools page.
