Kamil Rybicki · Opublikowano: · Zaktualizowano:
.htaccess to plik konfiguracyjny serwera Apache, który steruje ruchem na stronie, zanim uruchomi się jakikolwiek skrypt. W praktyce najczęściej służy do trzech rzeczy: przekierowania 301 ze starego adresu na nowy, wymuszenia jednej wersji domeny (HTTPS, z www lub bez) oraz blokowania niechcianego ruchu po adresie IP czy nazwie bota. Plik działa wyłącznie na serwerach Apache i LiteSpeed, na Nginx te same reguły trzeba przepisać bezpośrednio w konfiguracji serwera.
Czym jest plik .htaccess i do czego służy?
Nazwa pliku to .htaccess, bez rozszerzenia i bez żadnego członu przed kropką, to jest cała nazwa. Serwer Apache sprawdza obecność takiego pliku w każdym katalogu, przez który przechodzi żądanie, i stosuje zawarte w nim reguły, zanim przekaże żądanie dalej do PHP czy innego języka wykonującego stronę.
Na hostingu współdzielonym to zwykle jedyny sposób na zmianę konfiguracji serwera, bo dostawca nie daje dostępu do głównego pliku httpd.conf. Dlatego .htaccess odpowiada nie tylko za przekierowania, ale też za strony błędów, ochronę hasłem, limity dostępu i nagłówki cache. Każdy podkatalog i każda subdomena mogą mieć własny plik .htaccess, który nadpisuje reguły z katalogu głównego dla tej konkretnej ścieżki.
Ograniczenie, o którym warto wiedzieć od razu: mechanizm działa tylko na serwerach Apache oraz kompatybilnym z nim LiteSpeed. Na Nginx plik .htaccess jest ignorowany, a te same reguły przepisuje się w bloku konfiguracyjnym server na poziomie systemu. Sprawdzenie, na jakim oprogramowaniu stoi hosting, jest pierwszym krokiem przed wdrożeniem jakiejkolwiek reguły, bo skopiowanie gotowego kodu na złą platformę niczego nie zmieni.
Tworzenie pliku .htaccess: lokalizacja, składnia, przykład
Plik powstaje w dowolnym edytorze tekstu, zapisany jako zwykły tekst, i trafia do katalogu głównego domeny (zwykle public_html albo www), jeśli reguły mają obowiązywać w całym serwisie. Notatnik systemowy Windows bywa problematyczny, bo domyślnie dopisuje rozszerzenie .txt do nazwy, dlatego wygodniej użyć edytora kodu (Notepad++, VS Code, Sublime Text) albo utworzyć plik od razu na serwerze przez menedżer plików hostingu.
Każdy zestaw reguł opartych na przekierowaniach zaczyna się od włączenia modułu:
„`
RewriteEngine On
„`
Bez tej linii kolejne dyrektywy RewriteCond i RewriteRule są ignorowane. Poniżej przykład pliku, który wymusza wersję bez www i przenosi jeden konkretny, usunięty adres:
„`
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.domena\.pl(.*) [NC]
RewriteRule ^(.*)$ https://domena.pl/$1 [R=301,L]
RewriteRule ^usuniety-adres$ https://domena.pl/nowy-adres [L,R=301]
„`
Pierwsza para linii sprawdza, czy żądanie przyszło z przedrostkiem www, i jeśli tak, przekierowuje na wersję bez www. Flaga [NC] oznacza, że wielkość liter w porównaniu nie ma znaczenia, [R=301] wysyła kod przekierowania stałego, a [L] każe Apache zatrzymać sprawdzanie kolejnych reguł po dopasowaniu tej. Druga reguła działa niezależnie, bo warunek jest zapisany bezpośrednio w jej pierwszym elemencie, uruchamia się tylko dla adresu domena.pl/usuniety-adres.
Zanim nowy plik trafi na serwer produkcyjny, warto przetestować go na kopii strony albo w środowisku testowym. Błędna reguła, najczęściej brakujący ukośnik albo zła kolejność flag, kończy się błędem 500 dla całej domeny. To oznacza realny przestój i utratę ruchu na czas naprawy, a nie problem tylko jednej podstrony.
Przekierowanie 301 w .htaccess: gotowe reguły i różnice względem 302
Przekierowanie 301 w .htaccess wykonuje dyrektywa RewriteRule, dla wzorców i całych grup adresów, albo prostsza Redirect 301, dla pojedynczego, znanego z góry adresu, bez modułu mod_rewrite. Kod 301 oznacza przekierowanie stałe: mówi przeglądarce i wyszukiwarce, że stary adres nie wróci, a jego wartość rankingowa ma zostać trwale przeniesiona na nowy adres. To podstawowe narzędzie przy zmianie adresu podstrony, migracji na nową domenę albo scalaniu dwóch wersji tego samego URL-a w jedną.
Pojedynczy adres, przez RewriteRule:
„`
RewriteEngine On
RewriteRule ^poprzedni-adres$ https://domena.pl/nowy-adres [L,R=301]
„`
Ten sam efekt bez modułu mod_rewrite:
„`
Redirect 301 /stara-podstrona.php https://domena.pl/nowa-podstrona.html
„`
Przeniesienie całej domeny na nowy adres:
„`
RewriteEngine On
RewriteCond %{HTTP_HOST} ^poprzednia-domena\.pl$ [NC]
RewriteRule ^(.*)$ https://nowa-domena.pl/$1 [L,R=301]
„`
| Metoda | Kod HTTP | Wymaga mod_rewrite | Kiedy stosować |
|---|---|---|---|
| RewriteRule … [R=301,L] | 301, stałe | Tak | Wzorce adresów, całe katalogi, migracja domeny |
| Redirect 301 | 301, stałe | Nie | Pojedynczy, znany z góry adres |
| RewriteRule … [R=302,L] | 302, tymczasowe | Tak | Testy, chwilowa promocja, strona w przebudowie |
| Meta refresh w HTML | brak kodu 3xx | Nie dotyczy | Odradzane w SEO, wyszukiwarka traktuje to jako sygnał znacznie słabszy niż przekierowanie serwerowe |
Różnica między 301 a 302 ma znaczenie finansowe, nie tylko techniczne. Google konsoliduje sygnały rankingowe wypracowane przez stary adres i przenosi je na docelowy URL wyłącznie przy przekierowaniu stałym (Google Search Central). Oznaczenie migracji jako tymczasowej, czyli kodem 302, sprawia, że wyszukiwarka długo trzyma w indeksie stary adres i nie przenosi na nowy pozycji, które wcześniej przynosiły ruch i zapytania. Przy migracji całego serwisu albo zmianie struktury adresów w sklepie pomyłka w kodzie przekierowania potrafi kosztować tygodnie spadku widoczności na frazach, które wcześniej generowały zapytania.
Najczęściej używane flagi w regułach RewriteRule:
- [L] (Last) – zatrzymuje sprawdzanie kolejnych reguł w pliku po dopasowaniu tej.
- [R=301] – wysyła nagłówek przekierowania stałego, sam zapis [R] bez numeru oznacza domyślnie 302.
- [NC] (No Case) – dopasowanie niezależne od wielkości liter.
- [OR] – łączy warunek z kolejnym przez logiczne LUB zamiast domyślnego ORAZ.
- [F] (Forbidden) – zwraca błąd 403 zamiast przekierowania, używane przy blokowaniu dostępu.
- [NS] (No Subrequest) – pomija regułę dla wewnętrznych żądań serwera.
Wymuszenie HTTPS i jednej wersji domeny (www albo bez www)
Wymuszenie HTTPS to reguła przekierowująca każde żądanie HTTP na jego odpowiednik szyfrowany:
„`
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
„`
Dziś ta reguła jest praktycznie obowiązkowa, nie opcjonalna. Certyfikat SSL, najczęściej darmowy i wystawiany automatycznie przez hosting w technologii Let’s Encrypt, jest standardem od lat, a przeglądarki oznaczają każdy adres bez HTTPS etykietą "Nie zabezpieczona" widoczną w pasku adresu, zanim strona w ogóle się załaduje.
Druga równie częsta reguła porządkuje wersję z przedrostkiem www i bez niego. Obie wersje pod dwoma różnymi adresami to dla wyszukiwarki dwa osobne URL-e z tą samą treścią, więc jedną z nich trzeba wybrać jako docelową.
Wymuszenie wersji bez www:
„`
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.domena\.pl$ [NC]
RewriteRule ^(.*)$ https://domena.pl/$1 [R=301,L]
„`
Wymuszenie wersji z www, reguła odwrotna:
„`
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domena\.pl$ [NC]
RewriteRule ^(.*)$ https://www.domena.pl/$1 [R=301,L]
„`
Wybór między wersją z www i bez www nie ma dziś większego znaczenia rankingowego, jeśli przekierowanie jest ustawione poprawnie i konsekwentnie. Ma za to znaczenie dla zaufania klienta. Strona logowania czy koszyk dostępne równolegle pod dwoma adresami bywają odbierane jako mniej wiarygodne, a w branżach wrażliwych na dane, jak płatności, brak spójnego, szyfrowanego adresu bywa powodem porzucenia transakcji przed jej finalizacją.
Blokowanie adresów IP, botów i ruchu odsyłającego
Blokadę pojedynczego adresu IP, strony odsyłającej albo konkretnego bota .htaccess realizuje przez dyrektywy Order i Deny (klasyczny zapis, wspierany na zdecydowanej większości hostingu przez moduł zgodności wstecznej; na Apache 2.4 odpowiednikiem jest Require ip) oraz przez warunek RewriteCond sprawdzający nagłówek żądania.
„`
blokada wszystkich odwiedzających
Deny from all
blokada jednego wybranego adresu IP
Order Deny,Allow
Deny from 123.45.67.0
„`
Blokada ruchu z konkretnej strony odsyłającej:
„`
RewriteEngine on
RewriteCond %{HTTP_REFERER} niechcianadomena\.pl [NC]
RewriteRule .* – [F]
„`
Użytkownicy, którym dostęp zostaje odmówiony, otrzymują kod błędu 403.
Blokowanie po nazwie bota działa na tej samej zasadzie, warunek sprawdza wtedy nagłówek User-Agent:
„`
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} nazwa-bota [NC]
RewriteRule .* – [F]
„`
Dawniej ta reguła służyła głównie do odcinania botów kopiujących treść i skanerów podatności. Dziś dochodzi do tego nowa kategoria: crawlery modeli językowych, takie jak GPTBot, ClaudeBot czy PerplexityBot, które pobierają treść strony na potrzeby odpowiedzi generowanych przez AI. Blokada po User-Agent w .htaccess technicznie działa też na nie, ale to metoda zawodna, bo nic nie zmusza bota do przedstawienia się prawdziwą nazwą. Standardowym i szerzej respektowanym sposobem zarządzania dostępem crawlerów AI jest plik robots.txt, to właśnie ten plik odpytują w pierwszej kolejności, zanim zaczną pobierać treść. .htaccess ma sens jako dodatkowa, twardsza bariera dla ruchu, który już zignorował robots.txt albo nigdy nie miał zamiaru go respektować.
Ochrona hasłem i zabezpieczenia WordPressa w .htaccess
Ochronę hasłem .htaccess realizuje przez plik towarzyszący .htpasswd, w którym login i zaszyfrowane hasło są trzymane osobno od kodu strony, a dostęp do wybranego katalogu wymaga podania ich w oknie logowania przeglądarki, zanim serwer w ogóle wyśle treść.
„`
<Files wp-login.php>
Order Deny,Allow
Deny from All
Satisfy Any
AuthName "Dostep chroniony"
AuthUserFile /sciezka/do/.htpasswd
AuthType Basic
Require valid-user
</Files>
„`
Plik .htpasswd zawiera login i hasło rozdzielone dwukropkiem, przy czym hasło musi być zaszyfrowane, nigdy zapisane jawnym tekstem. Dziś najprostszym i najbardziej aktualnym sposobem wygenerowania takiego wpisu jest polecenie htpasswd z pakietu narzędzi Apache, uruchamiane przez SSH, albo wbudowany generator w panelu hostingowym: cPanel, DirectAdmin i Plesk mają gotową opcję "Password Protect Directories".
Popularna, wciąż aktualna para reguł chroniących instalację WordPress:
„`
blokada bezpośredniego dostępu do pliku konfiguracyjnego
<Files wp-config.php>
Order allow,deny
Deny from all
</Files>
blokada wykonywania plików PHP w katalogu przesyłania mediów
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/wp-content/uploads/.*\.php$ [NC]
RewriteRule .* – [F,L]
„`
Blokada wykonywania PHP w katalogu uploads jest jedną z tańszych metod ochrony, bo folder przesyłania plików jest typowym celem ataków umieszczających złośliwy skrypt pod pozorem obrazka. Coroczne raporty o bezpieczeństwie WordPressa wskazują, że zdecydowana większość ataków wykorzystuje znane, niezałatane luki w popularnych wtyczkach, a nie błędy w samym rdzeniu CMS-a (Patchstack).
Konsekwencja przejęcia strony rzadko kończy się na samej stronie. Google potrafi oznaczyć zainfekowaną domenę ostrzeżeniem w wynikach wyszukiwania i w przeglądarce (Google Transparency Report), co na czas czyszczenia i ponownego przeglądu odcina cały ruch organiczny. To bywa dłuższe i droższe niż samo wdrożenie reguł zabezpieczających na starcie.
Strona błędu 404, ochrona przed hotlinkowaniem i cache plików statycznych
Własną stronę błędu 404 ustawia jedna linia (ErrorDocument), ochronę przed hotlinkowaniem obrazków blokada oparta o nagłówek odsyłający, a przyspieszenie ładowania powtórnych odsłon nagłówek Cache-Control dla plików statycznych.
„`
ErrorDocument 404 /404.html
ErrorDocument 403 /403.html
„`
Własna strona błędu 404 zatrzymuje część odwiedzających, którzy trafili na nieistniejący adres, czy to literówka, usunięty produkt, czy stary link z innej strony, zamiast tracić ich od razu. Wystarczy umieścić na niej wyszukiwarkę wewnętrzną i link do kilku głównych kategorii, żeby część tego ruchu trafiła gdzie indziej w serwisie, zamiast się odbić.
Blokada hotlinkowania grafik:
„`
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domena\.pl/.*$ [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ – [F]
„`
Reguła blokuje wyświetlanie plików graficznych na cudzych stronach przez bezpośredni adres do pliku na serwerze właściciela, co poza kosztem transferu bywa też problemem praw autorskich do zdjęć.
Cache dla plików statycznych:
„`
<FilesMatch "\.(css|js|jpg|jpeg|png|gif|webp|svg|ico)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>
„`
Nagłówek Cache-Control mówi przeglądarce, żeby przy kolejnej wizycie nie pobierała ponownie tych samych plików CSS, skryptów czy grafik, tylko skorzystała z kopii zapisanej lokalnie. Ma to bezpośredni wpływ na czas wczytania strony przy powrocie użytkownika, a więc i na wskaźniki szybkości typu Largest Contentful Paint, które Google liczy do oceny jakości strony (web.dev). Przy sklepie internetowym czy formularzu kontaktowym każda dodatkowa sekunda ładowania zwiększa ryzyko, że odwiedzający zamknie kartę, zanim strona zdąży się w pełni wyświetlić.
Wyrażenia regularne w .htaccess: końcówki .html, parametry, przyjazne adresy
Wyrażenia regularne pozwalają dopasować całe wzorce adresów zamiast pojedynczych, znanych z góry URL-i, więc jedna reguła potrafi obsłużyć tysiące podstron naraz.
Usunięcie końcówek .html z adresów:
„`
RewriteCond %{THE_REQUEST} \.html
RewriteRule ^(.*)\.html$ /$1 [R=301,L]
„`
Przyjazne adresy zamiast parametrów w URL:
„`
RewriteCond %{REQUEST_URI} ^/kategoria/ [NC]
RewriteRule ^kategoria/([0-9]+)/?$ /index.php?kategoria=$1 [L]
„`
Takie reguły są typowe przy migracji sklepu ze starego systemu adresów, z parametrami albo końcówkami .php czy .html, na czytelne, przyjazne adresy. Zmiana struktury adresów całego serwisu bez kompletu przekierowań 301 ze starych wzorców na nowe kasuje historię rankingową setek podstron naraz. Przy większych wdrożeniach dobrze jest wcześniej wypisać pełną mapę starych i nowych adresów, zanim reguły trafią na serwer produkcyjny.
Najczęstsze pytania o .htaccess i przekierowania 301
Czym różni się przekierowanie 301 od 302?
301 oznacza przekierowanie stałe i mówi wyszukiwarce, że stary adres nie wróci, więc jego wartość rankingowa ma trwale przejść na nowy URL. 302 to przekierowanie tymczasowe, po którym wyszukiwarka nadal traktuje stary adres jako docelowy i nie przenosi na nowy pozycji ani ruchu. Kod 302 ma sens przy testach, promocjach czy stronie chwilowo wyłączonej z ruchu, przy trwałej zmianie adresu właściwym wyborem jest 301.
Dlaczego po dodaniu reguły w .htaccess strona pokazuje błąd 500?
Najczęstszą przyczyną jest literówka w składni, brakujący ukośnik albo zła kolejność flag, albo próba użycia dyrektywy, której akurat ta konfiguracja serwera nie obsługuje. Drugi typowy powód to brak włączonego modułu FollowSymlinks, wymaganego przez część reguł opartych na blokadzie stron odsyłających. Najbezpieczniejszy sposób namierzenia błędu to cofnięcie ostatnio dodanego fragmentu i wdrażanie kolejnych reguł pojedynczo, ze sprawdzeniem strony po każdej zmianie.
Czy plik .htaccess działa na każdym hostingu?
Nie, wyłącznie na serwerach z Apache albo kompatybilnym LiteSpeed, na których stoi zdecydowana większość hostingu współdzielonego w Polsce. Na Nginx plik .htaccess jest całkowicie ignorowany, a te same reguły administrator przepisuje bezpośrednio w konfiguracji serwera. Przed wdrożeniem reguł dobrze sprawdzić w panelu hostingowym albo u dostawcy, na jakim oprogramowaniu stoi serwer.
Czy błędnie skonfigurowane przekierowania szkodzą widoczności w Google?
Tak, najczęstszy problem to pętla przekierowań, gdy adres A prowadzi do B, a B z powrotem do A, albo zbyt długi łańcuch kilku przekierowań z rzędu, który spowalnia wczytanie strony i utrudnia robotom dotarcie do finalnego adresu. Równie kosztowny bywa brak przekierowania 301 przy zmianie adresu, wtedy stary URL po prostu znika z wyników razem z wypracowaną przez lata pozycją, zamiast przekazać ją dalej. Każdą większą zmianę struktury adresów dobrze sprawdzić w Search Console kilka tygodni po wdrożeniu, żeby potwierdzić, że nowe adresy przejęły ruch ze starych.
Czym jest RewriteCond i czym różni się od RewriteRule?
RewriteCond definiuje warunek, który musi być spełniony, żeby zadziałała następująca po nim reguła, na przykład konkretna domena w adresie albo brak szyfrowania. RewriteRule to sama komenda: adres, który ma zostać dopasowany, i to, co ma się z nim stać, czyli przekierowanie, blokada albo przepisanie na inny plik. Reguła bez warunku działa zawsze, gdy dopasuje adres, z warunkiem tylko wtedy, gdy oba elementy są spełnione naraz.



