WordPress .htaccess Weiterleitungen: 301 richtig gemacht
Eine URL verschieben, ohne Rankings zu verlieren: welche .htaccess Direktive in WordPress passt, wo die Regeln stehen müssen und wie du testest, ohne dich auszusperren.
Veröffentlicht
Du verschiebst eine URL und willst, dass die alte ihre Rankings behält? Dafür brauchst du eine 301 in der .htaccess — an einer Stelle, an der WordPress sie nicht löscht, mit der richtigen Direktive geschrieben und auf genau die URL gerichtet, die WordPress wirklich ausliefert. Geht eines dieser drei Dinge schief, bekommst du eine Weiterleitungskette, eine Endlosschleife oder einen 500er, der dich aus wp-admin aussperrt.
Erst die Entscheidung, dann die Platzierung, dann der Test — in dieser Reihenfolge.
Welche Direktive: Redirect, RedirectMatch oder RewriteRule
Im Spiel sind zwei Apache-Module, und die sind nicht austauschbar.
Redirect (mod_alias) — ein bekannter Pfad auf ein Ziel. Das Einfachste, was funktioniert:
Redirect 301 /old-page/ https://example.com/new-page/
Zwei Verhaltensweisen solltest du kennen. Die Direktive greift auf einem Pfadpräfix, nicht auf einer exakten Zeichenkette: /old-page/ erwischt also auch /old-page/anything/ und hängt /anything/ ans Ziel an. Und sie überträgt den Query-String automatisch mit.
RedirectMatch (mod_alias) — ein regulärer Ausdruck für viele URLs. So verschiebst du einen ganzen Bereich:
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1
Die Gruppe (.*) wird im Ziel zu $1, also landet /blog/hello-world/ auf /articles/hello-world/. Achte auf den führenden Schrägstrich: mod_alias vergleicht den vollständigen URL-Pfad.
RewriteRule (mod_rewrite) — nötig, wenn die Weiterleitung von einer Bedingung abhängt: Hostname, Protokoll, Query-String, User-Agent. Nichts in mod_alias kann so etwas prüfen.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
In einer verzeichnisbezogenen .htaccess wird dem Muster der führende Schrägstrich abgeschnitten — deshalb steht hier ^(.*)$ und im mod_alias-Beispiel ^/blog/. Diese Verwechslung ist der mit Abstand häufigste Grund dafür, dass eine kopierte Regel wortlos nichts tut.
Nimm im Zweifel mod_alias. Greif nur dann zu RewriteRule, wenn du wirklich eine Bedingung brauchst. Weniger reguläre Ausdrücke, weniger Fehlerquellen.
Wo die Regeln stehen müssen
Eigene Weiterleitungen gehören oberhalb der Zeile # BEGIN WordPress. Nicht hinein.
# --- custom redirects ---
Redirect 301 /old-page/ https://example.com/new-page/
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1
# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Dafür gibt es zwei voneinander unabhängige Gründe:
- WordPress überschreibt seinen eigenen Block. Das Speichern unter Einstellungen → Permalinks ruft
flush_rewrite_rules()auf, verwirft alles zwischen den Markern und erzeugt es neu. Eine Regel, die du dort hineingeschrieben hast, verschwindet, sobald jemand diese Seite anfasst — womöglich Monate später, ohne dass jemand die beiden Ereignisse in Verbindung bringt. - Die Reihenfolge entscheidet. Der WordPress Block endet mit einer Auffangregel, die jede Anfrage ohne passende Datei oder Verzeichnis an
index.phpschickt. EineRewriteRuledahinter wird nie ausgeführt.
Eine ehrliche Komplikation: mod_alias und mod_rewrite laufen nicht wirklich in Dateireihenfolge. Apache verarbeitet mod_alias während der URL-Übersetzung und das verzeichnisbezogene mod_rewrite später in der Fixup-Phase — eine Redirect Zeile kann also gegen eine RewriteRule gewinnen, die in der Datei darüber steht. Wenn du beide auf überlappenden Pfaden brauchst, entscheide dich für ein Modul pro Pfad und bleib dabei. Einen Streit zwischen mod_alias und mod_rewrite zu debuggen ist die Stunde nicht wert.
Abschließende Schrägstriche
Die kanonische Weiterleitung von WordPress hängt an die meisten Permalinks einen Schrägstrich an. Das hier:
Redirect 301 /old-page/ https://example.com/new-page
erzeugt also zwei Sprünge — deine 301 auf die URL ohne Schrägstrich, danach WordPress’ eigene 301, die den Schrägstrich ergänzt. Ketten geben Ranking-Signale weiter, verbrauchen aber Crawl-Budget und kosten jeden Besucher einen zusätzlichen Roundtrip.
Ruf das Ziel zuerst im Browser auf, kopiere die URL genau so, wie sie sich in der Adresszeile einpendelt, und nimm diese. Endet deine Permalink-Struktur auf .html oder ganz ohne Schrägstrich, richte dich danach. Es gibt hier keine allgemeingültige Antwort, nur: „triff das, was WordPress ausliefert“.
Testen, ohne sich auszusperren
Die .htaccess wird bei jeder Anfrage gelesen. Ein Syntaxfehler liefert für die gesamte Website einen 500er zurück, wp-admin eingeschlossen — der Rückweg muss also stehen, bevor du ihn brauchst.
Sichere zuerst die Datei. Über SSH:
cp /path/to/wordpress/.htaccess /path/to/wordpress/.htaccess.bak
Liefert die Website einen 500er, benennst du die kaputte Datei einfach wieder um und die Website ist sofort zurück. Halte in einem zweiten Fenster eine SFTP-Sitzung offen — sich bei ausgefallener Website erst neu einzuloggen, ist der Moment, in dem die Panik anfängt. Beachte außerdem: apachectl configtest liest die .htaccess nicht aus, meldet also eine gesunde Konfiguration, während deine Website tot ist.
Teste mit curl, nicht im Browser. Browser cachen 301-Antworten hart und zeigen dir bereitwillig das Ergebnis von gestern:
curl -sI https://example.com/old-page/ | head -n 5
Zwei Dinge sind wichtig: In der Statuszeile muss 301 stehen, und der Location: Header muss exakt die endgültige URL enthalten. Um die ganze Kette zu sehen, folgst du ihr:
curl -sIL https://example.com/old-page/ | grep -E '^(HTTP|Location)'
Mehr als eine Zeile HTTP/1.1 301 heißt: Du hast eine Kette gebaut. Mehr als etwa fünf heißt: Du hast eine Endlosschleife gebaut, und curl bricht ab und sagt es dir.
Nimm eine 302, solange du unsicher bist. Eine 302 wird nicht auf dieselbe Weise gecacht, ein Fehler ist also in Sekunden rückgängig gemacht. Stell auf 301 um, sobald curl das gewünschte Ziel zeigt. Das kostet nichts und hat mehr Websites gerettet als jede andere Angewohnheit in diesem Artikel.
Wenn eine Regel scheinbar überhaupt nichts tut, prüfe zuerst, ob Apache die Datei überhaupt liest. AllowOverride None auf dem Verzeichnis lässt Apache die .htaccess komplett ignorieren, und nginx ignoriert sie ohnehin vollständig — schau dir den Server: Header mit curl -I an, bevor du reguläre Ausdrücke debuggst. Um den Block mit der richtigen Syntax für deine Apache-Version und deinen Installationspfad zusammenzubauen, nutze den WordPress .htaccess Generator.
Wann .htaccess der falsche Ort ist
Für eine Handvoll Weiterleitungen, die Redakteure selbst pflegen sollen, ist ein Weiterleitungs-Plugin mit Regeln in der Datenbank das bessere Werkzeug: Es übersteht Hoster-Umzüge und braucht keinen SSH-Zugang. Der Nachteil ist real — php muss starten, um die Weiterleitung auszuliefern, und das ist langsamer, als wenn Apache direkt antwortet.
Nutze die .htaccess für strukturelle, dauerhafte Umzüge: Domainwechsel, Umbenennung eines Bereichs, Erzwingen von https oder www. Nutze ein Plugin für einzelne redaktionelle Weiterleitungen. Beides parallel ist in Ordnung, solange du weißt, welche Ebene welche URL besitzt — denn eine an zwei Stellen definierte Weiterleitung ist ein Fehler, der auf einen schlechten Nachmittag wartet.
FAQ
Fragen
Wohin gehören eigene Weiterleitungen in der WordPress .htaccess Datei?
Oberhalb der Zeile # BEGIN WordPress, niemals zwischen die Marker. WordPress erzeugt alles innerhalb dieser Marker neu, sobald jemand die Permalinks-Einstellungen speichert — eine Regel dort drin wird ohne Vorwarnung gelöscht. Auch die Reihenfolge hängt an der Platzierung: der WordPress Block endet mit einer Auffangregel, die alle nicht zugeordneten Anfragen an index.php schickt.
Soll ich Redirect, RedirectMatch oder RewriteRule für eine 301 nehmen?
Redirect für einen einzelnen bekannten Pfad, RedirectMatch wenn ein Muster viele URLs abdeckt, und RewriteRule wenn die Weiterleitung von einer Bedingung abhängt — Hostname, Protokoll oder Query-String. Redirect und RedirectMatch stammen aus mod_alias und sind einfacher. RewriteRule kommt aus mod_rewrite und ist die einzige Direktive, die Bedingungen prüfen kann.
Warum erzeugt meine .htaccess Weiterleitung eine Endlosschleife?
Meistens trifft das Ziel weiterhin auf die Regel zu, die den Besucher dorthin geschickt hat, also greift die Regel immer wieder. Die zweite häufige Ursache ist ein erzwungenes https hinter einem Load Balancer oder CDN: der Server sieht bei jeder Anfrage einfaches http, obwohl der Besucher längst verschlüsselt unterwegs ist. Prüfe stattdessen den Header X-Forwarded-Proto.
Spielt ein abschließender Schrägstrich bei einer WordPress Weiterleitung eine Rolle?
Ja. Die kanonische Weiterleitung von WordPress hängt an die meisten Permalinks einen Schrägstrich an. Zeigt deine 301 auf eine URL ohne Schrägstrich, entstehen zwei Sprünge statt einem. Verkettete Weiterleitungen geben Ranking-Signale zwar weiter, verbrauchen aber Crawl-Budget und bremsen den Besucher. Triff genau die Ziel-URL, die WordPress tatsächlich ausliefert — samt Schrägstrich.
Wie teste ich eine .htaccess Weiterleitung, ohne meine Website zu zerlegen?
Ruf die alte URL mit curl so auf, dass nur die Header abgefragt werden, und lies Statuscode und Location-Header, bevor du einem Browser glaubst. Browser cachen 301-Antworten sehr aggressiv und zeigen dir ein veraltetes Ergebnis. Sichere vorher eine Kopie der funktionierenden Datei, denn ein Syntaxfehler in .htaccess liefert auf jeder Seite einen 500er zurück — auch in wp-admin.
Warum liefert meine ganze Website nach dem Hinzufügen einer Weiterleitung einen 500er?
Eine einzige fehlerhafte Direktive in .htaccess legt jede URL unterhalb dieses Verzeichnisses lahm, das Backend eingeschlossen. Typische Ursachen sind ein nicht geschlossener IfModule-Block, eine fehlende Zeile RewriteEngine On oder die Zugriffssyntax von Apache 2.2 und 2.4 gemischt in einer Datei. Entferne den zuletzt hinzugefügten Block und lade neu, um das zu bestätigen.