Base64 vs kodowanie URL: jaka jest różnica?
Dwa schematy kodowania, które brzmią podobnie i są nieustannie mylone. Oto co robi każdy, gdzie są używane i dlaczego nie powinieneś ich mylić.
“Kodowanie Base64” i “kodowanie URL” brzmią, jakby powinny robić podobne rzeczy - oba konwertują dane na inną reprezentację używając tylko bezpiecznych znaków. Ale rozwiązują różne problemy, produkują bardzo różne wyjście i działają w różnych miejscach. Mylenie ich to niezawodny sposób na psute API, masakrowane linki i godziny debugowania w złym miejscu.
Oba kodowania zestawione
| Base64 | Kodowanie URL (percent-encoding) | |
|---|---|---|
| Cel | Reprezentacja danych binarnych jako tekstu | Uczynienie stringów bezpiecznymi dla URL-i |
| Alfabet | 64 znaki (A-Z, a-z, 0-9, +, /) | Dowolny drukowalny ASCII, używa %XX dla niebezpiecznych znaków |
| Przyrost rozmiaru | Dokładnie +33% | Zmienny (zwykle +0-200% zależnie od zawartości) |
| Używany w | Email, JSON, data URI, JWT | URL-e, wysyłki formularzy, query stringi |
| Wejście | Bajty | Tekst (zwykle string ze znakami specjalnymi) |
Co naprawdę robi kodowanie URL
Kodowanie URL (formalnie percent-encoding, zdefiniowane w RFC 3986) pozwala umieścić dowolny tekst w URL bez jego psucia.
URL-e mają strukturę:
https://example.com/search?q=coffee&lang=en
Pewne znaki mają specjalne znaczenie: ? oddziela ścieżkę od query stringa, & oddziela parametry, = oddziela klucz od wartości, / oddziela segmenty ścieżki, # rozpoczyna fragment.
Jeśli chcesz zawrzeć któryś z tych znaków jako dane - powiedzmy zapytanie “A & B” - musisz je escape’ować. Kodowanie URL zastępuje każdy znak specjalny znakiem % i dwucyfrowym kodem szesnastkowym ASCII:
- Spacja →
%20(lub+w query stringach) &→%26=→%3D#→%23
A & B staje się więc A%20%26%20B. Bezpieczne znaki (litery, cyfry, -, _, ., ~) przechodzą nienaruszone. Dla wejścia pełnego znaków specjalnych wynik potrafi być kilkukrotnie dłuższy.
Co naprawdę robi Base64
Base64 to zupełnie inna historia. Bierze bajty - niekoniecznie tekst - i produkuje string z 64-znakowego alfabetu. Każde 3 bajty wejścia stają się 4 znakami wyjścia, zawsze.
Base64 nie dba o to, czym jest wejście. Traktuje wszystko jako bajty i wyprowadza string bezpieczny do umieszczenia praktycznie wszędzie, gdzie spodziewany jest tekst. Wyjście jest dokładnie 33% dłuższe od wejścia (plus padding do wielokrotności 4 znakami =).
Sięgasz po Base64, gdy musisz przepuścić dane binarne (obraz PNG, plik zip, zaszyfrowany blob) przez kanał tylko tekstowy jak email albo JSON. Kodowanie URL tego nie obsłuży - jest projektowane do transformacji tekst-do-tekstu, nie do dowolnych binarów.
Kiedy potrzebujesz obu naraz
Jest jeden konkretny scenariusz, gdzie oba kodowania się spotykają: umieszczanie danych binarnych w URL-u.
Masz maleńki obraz (20 bajtów PNG) i chcesz go osadzić w URL jako parametr:
- Zakoduj obraz w Base64 → dostajesz 28-znakowy string
- Zakoduj ten string w URL → znaki
+,/i=stają się%2B,%2F,%3D
Ponieważ ta kombinacja jest tak powszechna, istnieje wariant Base64 URL-safe. Używa - i _ zamiast + i / (bezpieczne w URL-ach bez escape’owania) i pomija padding =:
- Standardowy Base64:
a+b/c= - URL-safe Base64:
a-b_c
JWT (JSON Web Tokens) używają właśnie URL-safe Base64 - stąd te stringi eyJhbGciOiJIUzI1NiJ9 bez żadnych + czy /.
Przykład obok siebie
Wejście: tekst Hello, world! (13 bajtów)
Kodowanie URL (escape’uje przecinek, spację i !):
Hello%2C%20world%21
Długość: 19 znaków. Wciąż czytelne.
Kodowanie Base64 (13 bajtów → tekst):
SGVsbG8sIHdvcmxkIQ==
Długość: 20 znaków. Nieczytelne.
URL-safe Base64 (bez znaków wymagających escape’owania):
SGVsbG8sIHdvcmxkIQ
Długość: 18 znaków. Używane w JWT i kompaktowych ID.
Kiedy używać kodowania URL
Po kodowanie URL sięgasz, gdy:
- Osadzasz dane użytkownika w ścieżce URL lub query stringu - wszystko, co człowiek wpisuje w pole wyszukiwania, wymaga kodowania URL przed wejściem do URL-a
- Escape’ujesz znaki specjalne w wysyłkach formularzy - formularze HTML domyślnie wysyłają dane URL-encoded
- Budujesz URL-e REST API z dynamicznymi parametrami (nazwy użytkowników, ID ze znakami specjalnymi, ścieżki plików)
Nie używaj kodowania URL do danych binarnych - bajty non-ASCII obsługuje niekonsekwentnie i marnuje miejsce na %-escape’y. Do plików binarnych najpierw Base64, potem ewentualnie kodowanie URL wyniku.
Kiedy używać Base64
Po Base64 sięgasz, gdy:
- Transmitujesz dane binarne przez kanał tylko tekstowy (JSON, email, XML)
- Osadzasz małe pliki w HTML lub CSS przez data URI
- Pracujesz z tokenami, certyfikatami, danymi kryptograficznymi, które przychodzą jako bajty, ale muszą być przechowywane jako tekst
- Udostępniasz pliki przez kopiuj-wklej, gdzie plik binarny by nie przeżył
Nie używaj Base64, gdy dane są już tekstem i potrzebujesz tylko escape’ować znaki dla URL - do tego służy kodowanie URL. I nie używaj go, gdy kanał jest binarnie bezpieczny - po prostu wyślij bajty bez zbędnego 33% narzutu.
Typowe scenariusze pomyłek
”Zakodowałem string w Base64, żeby umieścić go w URL, i wciąż jest zepsute”
Wyjście Base64 zawiera +, / i = - znaki ze specjalnym znaczeniem w URL-ach. Musisz albo zakodować string Base64 w URL, albo użyć wariantu URL-safe Base64 (który zamiast + i / używa - i _).
”Zakodowałem plik w URL, ale jest uszkodzony”
Kodowanie URL traktuje wejście jako tekst. Bajty non-ASCII są obsługiwane niekonsekwentnie zależnie od zakładanego kodowania. Dla plików binarnych Base64 najpierw, kodowanie URL wyniku tylko jeśli konieczne.
”API mówi, żeby zakodować hasło w Base64 dla Basic Auth”
HTTP Basic Auth bierze username:password, koduje cały string w Base64 i umieszcza w nagłówku Authorization. To nie dlatego, że Base64 jest bezpieczne - nie jest. Chodzi o to, że nagłówek musi przetrwać transmisję przez systemy, które mogłyby zmasakrować surowy tekst z dwukropkami i znakami specjalnymi. Bezpieczeństwo pochodzi z HTTPS, nie z Base64.
Praktyczny workflow
Nasze narzędzie Base64 obsługuje kodowanie i dekodowanie bez zbędnych kroków:
- Wklej tekst → dostajesz Base64 (do osadzenia w JSON, data URI itd.)
- Wklej Base64 → dostajesz tekst (do czytania JWT, dekodowania tokenów)
- Wgraj plik → dostajesz Base64 (do transmisji pliku jako tekstu)
Dla samego kodowania URL każdy język ma jednolinijkowiec:
- JavaScript:
encodeURIComponent(str)/decodeURIComponent(str) - Python:
urllib.parse.quote(str)/urllib.parse.unquote(str) - PHP:
urlencode($str)/urldecode($str) - Ruby:
CGI.escape(str)/CGI.unescape(str)
Dla scenariuszy łączonych (dane binarne w URL) standardowy wzorzec to: najpierw Base64, potem kodowanie URL jeśli potrzebne - albo od razu URL-safe Base64.
Zasada prosta do zapamiętania: kodowanie URL dla tekst-do-URL, Base64 dla bajty-do-tekstu. Gdy to zinternalizujesz, pomyłki znikają. A narzędzie Base64 jest do tłumaczenia bajty-do-tekstu, działa lokalnie - więc nawet wrażliwe tokeny zostają na twoim urządzeniu.