Base64URL Encoder & Decoder
Encode and decode URL-safe Base64 (RFC 4648 §5) with - and _ alphabet, no padding.
Docify's Base64url encoder implements RFC 4648 §5, using - and _ instead of + and /, with padding omitted. Example: >>>??? encodes to Pj4-Pz8_. This format is safe for URLs, query strings, cookies, and filenames. Used by JWT tokens for the header and payload. For standard Base64 with +/=, use the Base64 tool. Nothing is uploaded.
How it works
- Encoding: Text is first encoded to UTF-8, then to standard Base64 using
btoa(). Then+is replaced with-,/with_, and=padding is stripped. - Decoding: Whitespace is stripped, optional padding is accepted, then
-and_are converted back to+and/before decoding. - Validation: The decoder rejects
+and/characters. If your input contains these, use the standard Base64 tool instead. - Download: Saves the result as a plain text file. This is the encoded/decoded string, not a binary file reconstruction.
Base64 to URL-safe string
To convert standard Base64 to Base64url:
- Replace
+with- - Replace
/with_ - Strip
=padding characters
To convert Base64url back to standard Base64:
- Replace
-with+ - Replace
_with/ - Add
=padding to make the length a multiple of 4
// JavaScript: Base64 to Base64url const base64url = base64 .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); // JavaScript: Base64url to Base64 const pad = '='.repeat((4 - base64url.length % 4) % 4); const base64 = base64url .replace(/-/g, '+') .replace(/_/g, '/') + pad;
Base64 vs Base64url
| Feature | Base64 | Base64url |
|---|---|---|
| RFC | 4648 §4 | 4648 §5 |
| Index 62 | + | - |
| Index 63 | / | _ |
| Padding | Required (=) | Optional |
| Use case | General encoding | URLs, JWTs, filenames |
Base64url in Python and Node
The snippets below encode UTF-8 bytes with the RFC 4648 §5 alphabet (A–Z, a–z, 0–9, -, and _) and omit = padding. That is the same Base64url this page returns for text. They are not standard Base64 (+ / /). For that alphabet, see Base64 vs Base64URL: URL-Safe Alphabet.
Node.js with Buffer
Node 16+ Buffer encoding 'base64url' is RFC 4648 §5 and omits padding, matching this page. Pass 'utf8' so the bytes match this page's encodeURIComponent path. Use 'base64' only when you want the standard alphabet:
const encoded = Buffer.from('>>>???', 'utf8').toString('base64url');
// "Pj4-Pz8_"
const decoded = Buffer.from(encoded, 'base64url').toString('utf8');
// ">>>???"Python with urlsafe_b64encode
base64.urlsafe_b64encode accepts bytes only — passing a str raises TypeError. Encode UTF-8 first, then strip = to match this page. CPython urlsafe_b64decode maps - / _ but still needs padding restored to a multiple of four:
import base64
encoded = base64.urlsafe_b64encode('>>>???'.encode('utf-8')).decode('ascii').rstrip('=')
# 'Pj4-Pz8_'
pad = '=' * ((4 - len(encoded) % 4) % 4)
decoded = base64.urlsafe_b64decode(encoded + pad).decode('utf-8')
# '>>>???'Standard b64encode / Node 'base64' writes Pj4+Pz8/ for the same input — this page rejects + and /. Python keeps = when the length needs it (f encodes to Zg==); this page and Node 'base64url' write Zg. NFC and NFD spellings of the same letter are different UTF-8 sequences, so they encode to different Base64url strings.
Base64url in the shell
Text encode on this page converts UTF-8 bytes with the RFC 4648 §5 alphabet (A–Z, a–z, 0–9, -, and _) and omits = padding, and does not wrap. GNU coreutils 8.31+ basenc --base64url uses that same alphabet. It wraps at 76 characters by default; pass -w 0 to match this page. GNU encode keeps = padding when the length needs it (f encodes to Zg==); this page writes Zg. echo appends a newline, so use printf to match this page's encoding of >>>???. macOS ships neither basenc nor a Base64url flag. Homebrew coreutils installs gbasenc. GNU base64 and openssl base64 are RFC 4648 §4 (+ / /), not this alphabet. These commands are RFC 4648 §5, not standard Base64.
GNU basenc (Linux)
Coreutils basenc --base64url reads a file or stdin. Decode with -d. GNU -i means --ignore-garbage on decode — it is not an input-file flag:
# Text without a trailing newline (same as this page when no pad is needed) printf '>>>???' | basenc --base64url -w 0 # Pj4-Pz8_ printf 'Pj4-Pz8_' | basenc --base64url -d # >>>???
GNU decode requires padding when the length is not a multiple of 4: Zg fails with basenc: invalid input. Restore = padding to a multiple of 4 first (Zg==). This decoder accepts optional padding. Extra = after a complete group (Pj4-Pz8_=) decodes the group, then errors. Newlines in the encoded stream are allowed; other non-alphabet bytes need -i. + and / fail with basenc: invalid input— this decoder rejects them too. Use the Base64 encoder. -i skips + and / as garbage; it does not treat them as the §4 alphabet. Windows has no basenc unless WSL. For Python on macOS or Windows, use the base64.urlsafe_b64encode block above. Alphabet details are in Base64 vs Base64URL: URL-Safe Alphabet.
FAQ
- Does this tool upload my text?
- No. All encoding and decoding runs in your browser using JavaScript. Nothing is sent to a server.
- What is the difference between Base64 and Base64url?
- Standard Base64 uses + and / which have special meaning in URLs. Base64url (RFC 4648 §5) replaces them with - and _ and typically omits the = padding characters. This makes it safe for URLs, cookies, and filenames.
- Why does Base64url omit padding?
- The = character is reserved in URLs. Since the decoder can calculate the padding needed from the string length (RFC 4648 §3.2), padding can safely be omitted. This tool omits padding on encode and accepts optional padding on decode.
- Is Base64url used in JWTs?
- Yes. JSON Web Tokens (JWT) use Base64url encoding for the header and payload sections. Use our JWT decoder to parse complete tokens. It decodes header and payload locally and does not verify signatures.
- Does encoding preserve Unicode normalization?
- Base64url preserves exact byte sequences without normalizing. NFC é (U+00E9) and NFD e+combining-accent encode to different strings because they have different UTF-8 byte representations.
- Can I paste standard Base64 to decode?
- No. This decoder rejects + and / characters since they indicate standard Base64 was used. Use the Base64 tool instead, or replace + with - and / with _ before decoding here.