.htaccess Nedir, Nerede Bulunur?

.htaccess (hypertext access), Apache web sunucusunun dizin bazında okuduğu bir yapılandırma dosyasıdır. Ana sunucu ayarlarına dokunmadan; yönlendirme, erişim kontrolü, önbellek ve sıkıştırma gibi kuralları klasör düzeyinde değiştirmenizi sağlar. Dosya adının başındaki nokta onu "gizli dosya" yapar.

Dosya genellikle sitenizin kök dizininde, yani cPanel'de public_html klasöründe bulunur. Eğer yoksa, düz metin editörüyle boş bir dosya oluşturup adını tam olarak .htaccess koyarak yükleyebilirsiniz (uzantısı olmadan, sadece .htaccess).

Bir kuralın çalışabilmesi için çoğu zaman mod_rewrite modülünün açık olması gerekir. Paylaşımlı hosting paketlerinin neredeyse tamamında bu modül aktiftir. Kendi sunucunuzu yönetiyorsanız, sanal sunucu seçeneklerini karşılaştırmak için VPS karşılaştırma ve VDS karşılaştırma sayfalarımıza göz atabilirsiniz.

💡 Bilgi: .htaccess yalnızca Apache ve LiteSpeed sunucularında çalışır. Nginx bu dosyayı okumaz; Nginx kullanıyorsanız aynı kuralları server bloğu içinde rewrite ve location yönergeleriyle tanımlamanız gerekir.
⚠️ Uyarı: Değişiklik yapmadan önce mevcut .htaccess dosyasının bir yedeğini alın (örn. .htaccess.bak). Tek bir yazım hatası tüm siteyi "500 Internal Server Error" ile kapatabilir. Bir kural işe yaramadığında ilk bakacağınız yer bu dosyadaki son değişikliktir.

www Yönlendirme (www ↔ çıplak alan)

Sitenizin hem www.siteniz.com hem de siteniz.com ile açılması Google gözünde çift içerik (duplicate content) sorununa yol açar. Tek bir tercih edilen sürüm belirleyip diğerini ona 301 ile yönlendirmelisiniz.

www'yu çıplak (kök) alan adına yönlendirmek için (yani www.siteniz.comsiteniz.com):

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]

Tersini, yani çıplak alanı www'ya yönlendirmek istiyorsanız (siteniz.comwww.siteniz.com):

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

İki sürümden yalnızca birini seçin; ikisini birden kullanmayın, aksi takdirde sonsuz yönlendirme döngüsü oluşur.

HTTPS Zorlama

Ücretsiz Let's Encrypt SSL sertifikasını kurduktan sonra tüm http:// trafiğini https:// adresine yönlendirmelisiniz. Bu, hem güvenlik hem de SEO için gereklidir. Aşağıdaki kural HTTP ile gelen her isteği güvenli sürüme 301 ile taşır:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Cloudflare veya bir ters proxy arkasındaysanız %{HTTPS} değeri her zaman doğru gelmeyebilir. Bu durumda proxy başlığını kontrol eden şu sürümü kullanın:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

HTTPS'i tarayıcıya "her zaman kullan" olarak dayatmak için HSTS başlığı da ekleyebilirsiniz. Bu, ilk ziyaretten sonra tarayıcının siteye asla HTTP ile bağlanmamasını sağlar:

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>
⚠️ Dikkat: HSTS'i yalnızca sertifikanızın sorunsuz çalıştığından ve otomatik yenilendiğinden emin olduktan sonra ekleyin. includeSubDomains ile eklerseniz tüm alt alan adlarınızın da geçerli SSL'e sahip olması gerekir; aksi halde bu adresler tarayıcıda açılmaz. SSL kurulumunu bilmiyorsanız cPanel SSL rehberimize bakın.

301 Kalıcı Yönlendirme Örnekleri

Site yapınızı değiştirdiğinizde eski adresleri yeni adreslere 301 ("kalıcı olarak taşındı") ile yönlendirmek, hem ziyaretçileri hem de arama motoru sıralamanızı korur. En sık kullanılan senaryolar:

Tek bir sayfayı yeni URL'ye yönlendirme:

Redirect 301 /eski-sayfa.html https://siteniz.com/yeni-sayfa/

Tüm bir klasörü başka klasöre yönlendirme (mod_rewrite ile, alt sayfalar dahil):

RewriteEngine On
RewriteRule ^blog/(.*)$ /yazilar/$1 [R=301,L]

Tüm siteyi başka bir alan adına taşıma (yol yapısını koruyarak):

RewriteEngine On
RewriteCond %{HTTP_HOST} ^eskisite\.com [NC]
RewriteRule ^(.*)$ https://yenisite.com/$1 [L,R=301]

Yönlendirme türleri arasındaki fark SEO açısından kritiktir. Aşağıdaki tablo hangi durumda hangisini kullanacağınızı özetler:

Kod Anlamı Ne Zaman Kullanılır?
301 Kalıcı taşındı URL kalıcı değişti; SEO değeri yeni adrese aktarılır
302 Geçici taşındı Bakım, kampanya gibi geçici durumlar; eski URL korunur
410 Kalıcı silindi Sayfa tamamen kaldırıldı, yerine yenisi yok
💡 İpucu: Kalıcı taşımalarda mutlaka R=301 kullanın. Google'ın 302'de link değerini yeni adrese aktarması çok daha yavaş ve belirsizdir. Yanlış yönlendirme türü, taşıma sonrası trafik kaybının en yaygın nedenidir.

Gzip / Brotli Sıkıştırma

Sıkıştırma, HTML, CSS ve JavaScript dosyalarınızı tarayıcıya göndermeden önce %60-80 oranında küçültür. Bu, sayfa yükleme hızını gözle görülür şekilde artırır ve Core Web Vitals puanınızı iyileştirir. Aşağıdaki blok gzip sıkıştırmayı doğru dosya türleri için açar:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml
    AddOutputFilterByType DEFLATE text/css text/javascript
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE application/xml application/rss+xml
    AddOutputFilterByType DEFLATE image/svg+xml application/x-font-ttf
</IfModule>

Sunucunuzda daha modern ve verimli olan Brotli açıksa, onu da güvenle etkinleştirebilirsiniz:

<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/css text/javascript
    AddOutputFilterByType BROTLI_COMPRESS application/javascript application/json
</IfModule>

Sıkıştırmanın çalıştığını doğrulamak için tarayıcı geliştirici araçlarında (F12) Network sekmesine bakın; yanıt başlıklarında Content-Encoding: gzip veya br görmelisiniz. Zaten sıkıştırılmış olan JPEG, PNG, MP4 gibi dosyalar için sıkıştırma açmaya gerek yoktur; onların önbellek ayarı daha önemlidir.

Tarayıcı Önbelleği (Cache)

Statik dosyaları (resim, CSS, JS, font) ziyaretçinin tarayıcısında önbelleğe almak, tekrar eden ziyaretlerde sayfanın neredeyse anında açılmasını sağlar. Expires başlıklarıyla her dosya türü için bir "son kullanma tarihi" belirlersiniz:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType image/x-icon "access plus 1 year"
    ExpiresByType text/html "access plus 0 seconds"
</IfModule>

Alternatif olarak, aynı işi Cache-Control başlığıyla da yapabilirsiniz. Bu yöntem, önbelleğin ne kadar süre "taze" sayılacağını saniye cinsinden belirtir:

<IfModule mod_headers.c>
    <FilesMatch "\.(jpg|jpeg|png|gif|webp|svg|ico|css|js|woff2)$">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>
</IfModule>
⚠️ Dikkat: HTML sayfalarını uzun süre önbelleğe almayın (yukarıda text/html için 0 saniye verdik). Aksi halde içeriği güncellediğinizde ziyaretçiler günlerce eski sürümü görebilir. CSS/JS dosyalarını uzun önbelleğe alacaksanız, dosya adına sürüm ekleyin (örn. style.css?v=12) ki güncelleme sonrası tarayıcı yeni sürümü çeksin.

Hotlinking, başka sitelerin sizin sunucunuzdaki resimleri kendi sayfalarında doğrudan göstermesidir. Bu, sizin bant genişliğinizi harcar. Aşağıdaki kural, resimlerinizin yalnızca kendi sitenizden ve Google arama sonuçlarından yüklenmesine izin verir:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?siteniz\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,NC]

Yukarıdaki kural izinsiz istekleri "403 Forbidden" ile reddeder. İsterseniz izinsiz sitelerde resim yerine bir "uyarı görseli" göstererek daha yumuşak bir yöntem uygulayabilirsiniz:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?siteniz\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ https://siteniz.com/uyari.png [R,L]

Görselleriniz için ayrı bir sunucu veya CDN kullanmayı düşünüyorsanız, kaynak ihtiyacınıza göre hosting karşılaştırma tablomuzdan bant genişliği limitlerini karşılaştırabilirsiniz.

Özel Hata Sayfaları

Varsayılan Apache hata sayfaları hem çirkin hem de marka güveninizi zedeler. Kendi tasarımınızda 404 (bulunamadı) ve 500 (sunucu hatası) sayfaları göstermek çok basittir. Önce hata sayfalarınızı oluşturun, sonra şu satırları ekleyin:

ErrorDocument 400 /hatalar/400.html
ErrorDocument 401 /hatalar/401.html
ErrorDocument 403 /hatalar/403.html
ErrorDocument 404 /hatalar/404.html
ErrorDocument 500 /hatalar/500.html

Yollar sitenizin kök dizinine göre yazılır (başında / ile). Örneğin /hatalar/404.html, public_html/hatalar/404.html dosyasını gösterir.

💡 İpucu: 404 sayfanıza arama kutusu, ana sayfaya dönüş bağlantısı ve popüler içeriklere linkler koyun. Böylece hatalı bağlantıya tıklayan ziyaretçiyi kaybetmek yerine siteye geri kazandırırsınız. Ayrıca hata sayfalarının gerçekten 404 durum kodu döndürdüğünden emin olun; yanlışlıkla 200 dönerse Google bu sayfaları dizine ekler.

Ek Güvenlik Kuralları

.htaccess ile birkaç satırda temel güvenlik seviyesini yükseltebilirsiniz. En yaygın ve faydalı kuralları aşağıda topladık.

Dizin listelemeyi kapatma (index dosyası olmayan klasörlerde dosyaların listelenmesini engeller):

Options -Indexes

Hassas dosyalara erişimi engelleme (.htaccess, wp-config.php gibi dosyaların doğrudan açılmasını yasaklar):

<FilesMatch "^\.(htaccess|htpasswd|env)$">
    Require all denied
</FilesMatch>

<Files wp-config.php>
    Require all denied
</Files>

Belirli bir IP adresinden erişimi engelleme (spam veya saldırı yapan bir adresi kesmek için):

<RequireAll>
    Require all granted
    Require not ip 203.0.113.45
</RequireAll>

Güvenlik başlıkları ekleme (clickjacking ve MIME sniffing gibi saldırılara karşı):

<IfModule mod_headers.c>
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "SAMEORIGIN"
    Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

Sunucunuzun genel erişilebilirliğini ve yanıt sürelerini izlemek için durum takip sayfamızdan yararlanabilirsiniz. Farklı barındırma türlerini karşılaştırmak isterseniz karşılaştırma aracımız size en uygun paketi seçmede yardımcı olur.

Sıkça Sorulan Sorular

.htaccess değişikliği neden 500 hatası veriyor?

En sık nedeni, sunucuda o kural için gereken modülün (örn. mod_rewrite, mod_headers) kapalı olması ya da bir yazım hatasıdır. Kuralları <IfModule ...> bloğu içine almak, modül yoksa hatayı önler. Sorun devam ederse, en son eklediğiniz satırları geçici olarak kaldırıp hatanın hangi satırdan geldiğini tespit edin.

.htaccess değişiklikleri hemen mi geçerli olur?

Evet. Apache .htaccess dosyasını her istekte yeniden okur, bu yüzden sunucuyu yeniden başlatmanıza gerek yoktur. Değişiklik anında yürürlüğe girer. Yalnızca tarayıcı önbelleği nedeniyle eski sürümü görebilirsiniz; sekmeyi zorla yenileyin (Ctrl+F5).

301 mi 302 mi kullanmalıyım?

Adres kalıcı olarak değiştiyse ve SEO değerini yeni adrese aktarmak istiyorsanız 301 kullanın. Yalnızca geçici bir durum (bakım, kampanya, A/B testi) söz konusuysa 302 kullanın. Kalıcı taşımalarda 302 kullanmak arama sıralamanızı olumsuz etkiler.

Nginx kullanıyorum, .htaccess çalışmıyor. Ne yapmalıyım?

Nginx .htaccess dosyasını okumaz. Aynı kuralları Nginx yapılandırma dosyasında (server bloğu içinde) rewrite, return 301 ve location yönergeleriyle tanımlamanız gerekir. Bu, genellikle root erişimi gerektirdiği için yönetimli olmayan VPS ya da dedicated sunucularda yapılır.

Gzip sıkıştırmanın açık olup olmadığını nasıl anlarım?

Tarayıcıda F12 ile geliştirici araçlarını açın, Network sekmesinde bir dosyaya tıklayın ve yanıt başlıklarında (Response Headers) Content-Encoding: gzip veya br satırını arayın. Bu satır varsa sıkıştırma çalışıyordur. Alternatif olarak çevrimiçi "gzip test" araçlarını da kullanabilirsiniz.