Skip to content
Bloga Dönün
Eğitimler

URL Kodlama ve Çözme: Yüzde Kodlaması Rehberi

RFC 3986 kuralları, encodeURI ile encodeURIComponent karşılaştırması, UTF-8 bayt eşlemesi ve JS, Python, Go, Java kod örnekleri. Ücretsiz aracımızı deneyin.

12 dakika okuma

URL Kodlama ve Çözme: Geliştiriciler için Yüzde Kodlaması Rehberi

Bir sunucu kayıt dosyasını izlerken bir query string içinde şunu görüyorsunuz: %E4%BD%A0%E5%A5%BD. Bozuk veri mi? Hata mı? Hiçbiri — bu, Çince 你好 karakterlerinin önce her birinin üç UTF-8 baytına dönüştürülüp ardından URL için güvenli bir biçimde yüzde kodlaması ile kodlanmış halidir. Her web geliştiricisi sonunda bu duvara çarpar: bir şey bozuk görünür, ama URL tam tasarlandığı gibi çalışmaktadır.

URL kodlaması — resmi adıyla yüzde kodlaması — özel karakterleri URL’ler için güvenli hale getiren mekanizmadır. Bu rehber, mekanizmanın bayt düzeyinde nasıl çalıştığını, ne zaman encodeURI yerine encodeURIComponent kullanmak gerektiğini, dört dilde doğru kodlamanın nasıl yapılacağını ve deneyimli geliştiricilerin bile takıldığı hataları ele alır.

Kodlama ve çözme işlemini gerçek zamanlı takip etmek için herhangi bir URL’yi URL Koder ve Çözücü aracımıza yapıştırın.

URL Kodlaması (Yüzde Kodlaması) Nedir?

Bir URL, ASCII karakterlerinin yalnızca küçük bir alt kümesini içerebilir. Harfler, rakamlar ve birkaç sembol internet üzerinde sorunsuz biçimde dolaşır. Geri kalan her şey — boşluklar, ve işaretleri, Çince metin, emoji — URL’lerin taşıyabileceği bir biçime dönüştürülmelidir.

Yüzde kodlaması her güvensiz baytı % işareti ile ardından gelen iki onaltılık basamakla değiştirir. Bir boşluk %20 olur. Bir ve işareti %26 olur. Adı bu % ön ekinden gelir.

Kurallar RFC 3986 belgesinde yer alır; 2005’te yayımlanmıştır ve hâlâ geçerli standarttır. RFC 2396’nın yerini almış, hangi karakterlerin güvenli, hangilerinin ayrılmış olduğunun ve ASCII dışı metnin nasıl ele alınacağının tanımını sıkılaştırmıştır.

Hızlı örnekler:

GirdiKodlanmışNeden
hello worldhello%20worldURL’lerde boşluğa izin verilmez
price=10&tax=2price%3D10%26tax%3D2= ve & yapısal anlam taşır
%E4%B8%ADASCII dışı → UTF-8 baytları → yüzde kodlu
🚀%F0%9F%9A%80Emoji → 4 UTF-8 baytı → yüzde kodlu

Hangi Karakterler Kodlama Gerektirir?

RFC 3986 karakterleri üç gruba ayırır.

Ayrılmamış Karakterler (Hiçbir Zaman Kodlanmaz)

Bu 66 karakter URL’nin herhangi bir bölümünde olduğu gibi geçer:

A-Z  a-z  0-9  -  .  _  ~

Harfler, rakamlar, kısa çizgi, nokta, alt çizgi, tilde. Listenin tamamı budur.

Ayrılmış Karakterler (Bağlama Bağlı)

Bu karakterler URL’lerde yapısal ayraç görevi görür:

KarakterURL yapısındaki rol
:Şemayı yetki bölümünden ayırır (https:)
/Yol parçalarını ayırır
?Query string’i başlatır
#Parça (fragment) başlatır
&Sorgu parametrelerini ayırır
=Parametre anahtarını değerden ayırır
@Kullanıcı bilgisini sunucudan ayırır
+ ! $ ' ( ) * , ; [ ]Çeşitli ayrılmış roller

Kural: ayrılmış bir karakter yapısal amacına hizmet ediyorsa olduğu gibi bırakın. Veri olarak görünüyorsa (örneğin bir parametre değerinin içinde), kodlayın.

Diğer Her Şey (Her Zaman Kodlanır)

Boşluklar, açılı parantezler, süslü parantezler, dikey çizgiler, ters bölü işaretleri ve ASCII dışı karakterler (Çince, Arapça, emoji) yüzde kodlamasından geçirilmelidir.

Bir incelik var: RFC 3986 boşlukları %20 olarak kodlar, ama HTML form gönderimleri + kullanır. Bu çatışmayı aşağıdaki “%20 ile +” bölümünde ele alıyoruz.

URL Kodlaması Aslında Nasıl Çalışır: UTF-8 Pipeline

ASCII karakterler için kodlama basittir: bayt değerini onaltılıkta arayın, başına % ekleyin. Bir boşluk (bayt değeri 32, hex 20) %20 olur.

ASCII dışı metinler için kodlamanın üç adımı vardır:

Adım 1 — Karakterden Unicode kod noktasına. é karakteri U+00E9 kod noktasına eşlenir. 🚀 emojisi U+1F680’e eşlenir.

Adım 2 — Kod noktasından UTF-8 baytlarına. UTF-8, kod noktası aralığına bağlı olarak 1 ila 4 bayt kullanır. é (U+00E9) iki bayt olur: 0xC3 0xA9. Roket emojisi (U+1F680) dört bayt olur: 0xF0 0x9F 0x9A 0x80.

Adım 3 — Her bayt için %XX. 2. adımdan gelen her bayt kendi yüzde kodlu üçlüsünü alır.

Çeşitli karakter tipleri için tüm pipeline aşağıdadır:

KarakterKod NoktasıUTF-8 BaytlarıKodlanmışBoyut çarpanı
AU+004141A (kodlanmaz)
boşlukU+002020%20
éU+00E9C3 A9%C3%A9
U+4E2DE4 B8 AD%E4%B8%AD
🚀U+1F680F0 9F 9A 80%F0%9F%9A%8012×

Bunu JavaScript ile kendiniz doğrulayabilirsiniz:

const char = '中';
const encoded = encodeURIComponent(char);
console.log(encoded); // '%E4%B8%AD'

// Baytları izle
const bytes = new TextEncoder().encode(char);
console.log([...bytes].map(b => '%' + b.toString(16).toUpperCase()).join(''));
// '%E4%B8%AD' — eşleşiyor

Bu genişleme, aşağıdaki “URL Uzunluk Sınırları” bölümünde ele aldığımız kısıtlar açısından önemlidir. 20 Çince karakter içeren bir URL, 180 karakterlik yüzde kodlu metin ekler.

encodeURI ile encodeURIComponent — Doğru Fonksiyonu Seçmek

Bu iki JavaScript fonksiyonu sürekli karıştırılır. Benzer görünürler ama çok farklı karakter kümelerini kodlarlar.

encodeURI()encodeURIComponent()
AmaçTam bir URL’yi kodlarTek bir bileşeni kodlar (parametre anahtarı veya değeri)
Korur: / ? # & = @ + $ ,Bunların hiçbirini korumaz
KodlarBoşluklar, ASCII dışı, bazı noktalama işaretleriA-Z a-z 0-9 - _ . ~ ! ' ( ) * dışındaki her şeyi
Ne zaman kullanılırYolda boşluk veya Unicode bulunan tam bir URL’niz varsaKullanıcı girdisinden sorgu parametreleri oluşturuyorsanız

Düzenli olarak üretime giden bir hata:

// ❌ HATA: encodeURI & karakterini kodlamaz
const search = 'Tom & Jerry';
const bad = `https://api.example.com/search?q=${encodeURI(search)}`;
// Sonuç: https://api.example.com/search?q=Tom%20&%20Jerry
// & query string'i böler — sunucu q=Tom%20 ve ayrı bir param %20Jerry görür

// ✅ DÜZELTME: encodeURIComponent & karakterini %26 olarak kodlar
const good = `https://api.example.com/search?q=${encodeURIComponent(search)}`;
// Sonuç: https://api.example.com/search?q=Tom%20%26%20Jerry

Tereddütteyseniz encodeURIComponent() seçin. Gerçek dünyadaki URL oluşturma senaryolarının yüzde 95’i için doğru tercihtir.

URL Koder aracımızda iki modu yan yana deneyin →

Her Dilde URL Kodlaması

JavaScript (Tarayıcı ve Node.js)

// Bir parametre değerini kodla
const value = encodeURIComponent('price >= 100 & currency = €');
// 'price%20%3E%3D%20100%20%26%20currency%20%3D%20%E2%82%AC'

// Çöz
const original = decodeURIComponent(value);
// 'price >= 100 & currency = €'

// Modern yaklaşım: URLSearchParams kodlamayı otomatik halleder
const params = new URLSearchParams({ q: 'hello world', lang: '中文' });
console.log(params.toString());
// 'q=hello+world&lang=%E4%B8%AD%E6%96%87'
// Not: URLSearchParams boşluklar için + kullanır (form kodlaması)

Python

from urllib.parse import quote, unquote, urlencode

# Bir yol parçasını kodla
quote('hello world/file name.txt', safe='/')
# 'hello%20world/file%20name.txt'

# Sorgu parametrelerini kodla
urlencode({'q': '你好', 'page': '1'})
# 'q=%E4%BD%A0%E5%A5%BD&page=1'

# quote_plus boşluklar için + kullanır (form kodlaması)
from urllib.parse import quote_plus
quote_plus('hello world')  # 'hello+world'
quote('hello world')       # 'hello%20world'

Go

import "net/url"

// Bir sorgu değerini kodla (boşluk için + kullanır)
url.QueryEscape("hello world & more")
// "hello+world+%26+more"

// Bir yol parçasını kodla (boşluk için %20 kullanır)
url.PathEscape("hello world & more")
// "hello%20world%20&%20more"

// url.Values ile bir URL'yi güvenli biçimde inşa et
params := url.Values{}
params.Set("q", "你好世界")
params.Set("page", "1")
fmt.Println(params.Encode())
// "page=1&q=%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C"

Java

import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// Kodla (boşluk için + kullanır — Java form kodlamasını izler)
String encoded = URLEncoder.encode("hello world & more", StandardCharsets.UTF_8);
// "hello+world+%26+more"

// RFC 3986 uyumu için + karakterini %20 ile değiştir
String rfc3986 = encoded.replace("+", "%20");
// "hello%20world%20%26%20more"

// Çöz
String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
// "hello world & more"

Go ve Java varsayılan olarak form kodlamasına başvurur (boşluklar + olur). RFC 3986 çıktısı için sonucu son işlemden geçirip + karakterini %20 ile değiştirin.

Üretimi Bozan Beş URL Kodlama Hatası

1. Çift Kodlama (%20 Yerine %2520)

Bir karakter dizisini kodlarsınız. Bir framework onu tekrar kodlar. %20 içindeki % %25 olur ve sunucu bir boşluk yerine düz %20 metni görür.

Belirti: URL’ler %2520, %253D veya başka %25xx desenleri içerir.

Tanı: Bir URL’deki %25, bir % karakterinin kodlandığı anlamına gelir; bu da çoğunlukla çift kodlamaya işaret eder.

Düzeltme: Önce çözün, sonra bir kez kodlayın. Kodlamadan önce girdinin zaten kodlanmış olup olmadığını denetleyin.

// Çift kodlamayı tespit et
function isDoubleEncoded(str) {
  return /%25[0-9A-Fa-f]{2}/.test(str);
}

// Güvenli kodlama: önce çöz, sonra kodla
function safeEncode(str) {
  try { str = decodeURIComponent(str); } catch (e) { /* kodlanmamış, sorun değil */ }
  return encodeURIComponent(str);
}

2. Yol Parçalarında +

Bir geliştirici, boşluklar için + çıktısı veren bir kütüphaneyle bir dosya adını URL kodlamasından geçirir. my report.pdf dosyası my+report.pdf olur. Sunucu + karakterini düz artı işareti olarak yorumlar ve 404 döndürür.

Kural: + yalnızca query string’lerde (yani ? sonrasında) boşluk anlamına gelir. Yol parçalarında + yalnızca +’tır. Yollarda boşluklar için her zaman %20 kullanın.

3. Bozuk OAuth Yönlendirme URI’leri

Yetkilendirme URL’si şuna benzer:

https://auth.provider.com/authorize?redirect_uri=https://myapp.com/callback?code=abc&state=xyz

OAuth sunucusu redirect_uri=https://myapp.com/callback?code=abc kısmını okur ve state=xyz parçasını ayrı bir üst düzey parametre olarak işler. Kimlik doğrulama başarısız olur.

Düzeltme: Yönlendirme URI değerinin tamamını kodlayın:

const redirectUri = 'https://myapp.com/callback?code=abc&state=xyz';
const authUrl = `https://auth.provider.com/authorize?redirect_uri=${encodeURIComponent(redirectUri)}`;
// redirect_uri=https%3A%2F%2Fmyapp.com%2Fcallback%3Fcode%3Dabc%26state%3Dxyz

4. Kayıtlardaki Bozuk ASCII Dışı Metin

Sunucu kayıtları okunabilir Çince karakterler yerine %E4%BD%A0%E5%A5%BD gösterir. URL doğru biçimde kodlanmıştır; yalnızca kayıt görüntüleyiciniz yüzde kodlu dizileri çözmüyordur.

Düzeltme: Kayıtları bir çözücüden geçirin veya orijinal metni okumak için URL’yi bir URL Çözücü aracına yapıştırın.

5. API İmza Hataları

OAuth 1.0 ve AWS Signature V4 sıkı RFC 3986 kodlaması gerektirir. JavaScript’in encodeURIComponent() fonksiyonu !, ', (, ) veya * karakterlerini kodlamaz. Bu karakterler imza girdinizde görünürse imza eşleşmez.

Düzeltme: Çıktıyı son işlemden geçirin:

function rfc3986Encode(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, c =>
    '%' + c.charCodeAt(0).toString(16).toUpperCase()
  );
}

%20 ile + — Boşluk Kodlama İkilemi

Bir tek karakterin nasıl kodlanacağı konusunda iki standart anlaşamaz.

StandartBoşluk şuna dönüşürNerede geçerlidir
RFC 3986 (URI sözdizimi)%20Bir URL’nin her yerinde
application/x-www-form-urlencoded+HTML form gönderimlerinden gelen query string’lerde

+ kuralı erken web tarayıcılarından kalma bir mirastır. Bir <form>, method="GET" ile gönderildiğinde tarayıcı boşlukları query string’de + olarak kodlar. HTML belirtimi bu davranışı resmileştirir.

Sorun şu: + yalnızca query string’lerde “boşluk” anlamına gelir. Yol parçalarında + düz bir artı işaretidir. Bu yüzden https://example.com/my+file.pdf, my file.pdf adlı bir dosyayı değil, my+file.pdf adlı bir dosyayı sunar.

Pratik öneri:

  • URL’leri elle inşa ederken veya yol parçalarını kodlarken %20 kullanın. Her yerde çalışır.
  • Form gönderimlerinden gelen query string’leri ayrıştırırken + karakterini kabul edin — framework’ünüz büyük olasılıkla bunu zaten ele alıyordur.
  • İki kuralı karıştırmayın. Her bileşen için bir kural seçin ve ona bağlı kalın.

URL Kodlaması ve Güvenlik

URL Kodlaması Şifreleme DEĞİLDİR

Yüzde kodlaması, kriptografik özelliği olmayan, tam tersine çevrilebilir, deterministik bir dönüşümdür. Herhangi biri %48%65%6C%6C%6F dizesini milisaniyeler içinde tekrar Hello’ya çözebilir.

Hassas verileri gizlemek için URL kodlamasını kullanmayın. İsteğin tamamını şifrelemek için HTTPS kullanın. URL’ler sunucu kayıtlarında, tarayıcı geçmişinde ve Referer header’lerinde görünür; bu yüzden hassas bilgiler URL’lerde değil, istek gövdelerinde yer almalıdır.

Open Redirect Saldırıları

Saldırganlar saf doğrulamayı aşmak için kodlanmış URL’ler kullanır. %2F%2Fevil.com içeren bir yönlendirme parametresi //evil.com olarak çözülür; tarayıcılar bunu saldırganın etki alanına işaret eden protokol-bağıl bir URL olarak yorumlar.

Savunma: Kodlanmış biçimi değil, çözülmüş URL’yi doğrulayın. Yönlendirme etki alanları için allowlist kullanın.

Çift Kodlama İstismarları

Bir WAF, gelen URL’leri <script> etiketleri için denetler. Bir saldırgan %253Cscript%253E gönderir. WAF yüzde kodlu metni görür ve geçirir. Uygulama bir kez çözer, %3Cscript%3E ortaya çıkar; ikinci bir çözme <script> üretir ve filtre aşılır.

Savunma: Güvenlik kontrolleri uygulamadan önce tüm girdiyi normalleştirin (tamamen çözün). Tek bir çözme adımına güvenmeyin.

Kimlik doğrulama tokenlarını URL’lerde ve Authorization header’lerinde taşırken karşılaşılan tuzaklar için JWT çözme rehberimize bakın.

URL Uzunluk Sınırları ve Kodlama Ne Zaman Pahalıya Mal Olur

HTTP belirtimi azami URL uzunluğu belirlemez, ama yığının her katmanı pratik sınırlar koyar.

KatmanSınır
Genel öneri2.000 karakter
Chrome, Firefox~2 MB (ama sunucular çok daha önce reddeder)
Apache (varsayılan)8.190 bayt
Nginx (varsayılan)8.192 bayt
IIS16.384 bayt (query string)
CDN’ler, proxy’lerDeğişken — genellikle 4.096-8.192 bayt

Yüzde kodlaması URL’leri uzatır. Tek bir Çince karakter 1 karakterden 9 karaktere (%E4%B8%AD) çıkar. Bir emoji 12’ye genişler. Bir query string’deki iki yüz Çince karakter tek başına 1.800 karakterlik yüzde kodlu metin üretir.

Sınıra ulaştığınızda: Veriyi sorgu parametrelerinden bir POST isteği gövdesine taşıyın. Arama arayüzleri için JSON kabul eden bir POST endpoint iyi bir çözümdür.

SSS

URL kodlaması nedir ve geliştiricilerin neden buna ihtiyacı vardır?

URL kodlaması (yüzde kodlaması), URL’lerde izin verilmeyen karakterleri %XX hex dizilerine dönüştürür. URL’ler yalnızca 66 ayrılmamış ASCII karakterini destekler. Boşluklar, ve işaretleri, Unicode metin ve çoğu noktalama işareti kodlanmalıdır; aksi takdirde URL yapısını bozarlar.

encodeURI ile encodeURIComponent arasındaki fark nedir?

encodeURI() ://, /, ? ve & gibi yapısal karakterleri korurken tam bir URL’yi kodlar. encodeURIComponent() ise A-Z a-z 0-9 - _ . ~ ! ' ( ) * dışındaki her şeyi kodlar. Sorgu parametresi değerleri için encodeURIComponent() kullanın. encodeURI() yalnızca elinizde tam bir URL varsa ve yapısını bozmadan boşlukları veya ASCII dışı karakterleri düzeltmek istiyorsanız kullanın.

URL’lerde %20 neden bazen + olarak görünür?

Her ikisi de bir boşluğu temsil eder, ama farklı standartlardan gelirler. %20 RFC 3986 kuralını izler ve URL’nin her yerinde çalışır. + HTML form kodlama belirtimini izler ve yalnızca query string’lerde çalışır. Yol parçalarında + düz bir artı işaretidir. Tereddütteyseniz %20 kullanın.

Python, JavaScript, Go ve Java’da metni nasıl URL kodlarım?

JavaScript: encodeURIComponent('hello world')hello%20world. Python: urllib.parse.quote('hello world')hello%20world. Go: url.QueryEscape("hello world")hello+world. Java: URLEncoder.encode("hello world", UTF_8)hello+world. Go ve Java varsayılan olarak form kodlamasına geçer (boşluk = +); RFC 3986 çıktısı için + karakterini %20 ile değiştirin.

URL kodlaması güvenlik veya şifreleme için kullanılabilir mi?

Hayır. URL kodlaması anahtar gerektirmeden tamamen tersine çevrilebilir. Sıfır gizlilik sağlar. Hassas verileri yüzde kodlamasıyla değil, HTTPS ile koruyun. URL’ler sunucu kayıtlarında, tarayıcı geçmişinde ve Referer header’lerinde görünür; bu yüzden hassas veriler istek gövdelerinde yer almalıdır.

Çift kodlama nedir ve nasıl düzeltirim?

Çift kodlama, zaten kodlanmış bir karakter dizisi tekrar kodlandığında ortaya çıkar. %20 içindeki % %25 olarak kodlanır ve %2520 üretir. Sunucular bir boşluk yerine düz %20 metni görür. Bunu düzeltmek için önce girdiyi çözün, sonra bir kez kodlayın. İki onaltılık basamağın izlediği %25 deseni belirgin bir işarettir.

Azami URL uzunluğu nedir?

HTTP belirtiminde resmi bir azami yoktur. Geniş uyumluluk için güvenli sınır 2.000 karakterdir. Apache varsayılanı 8.190 bayt, Nginx ise 8.192 bayttır. ASCII dışı karakterler yüzde kodlandığında 3-12 kat genişler; bu yüzden uluslararasılaştırılmış URL’ler sınırlara daha hızlı ulaşır. Büyük yükler için POST’a geçin.