
.htaccess audit: why the site returns 500 and which rules do not work
Drop the file in — the tool will find the BOM, dead directives, rules with a high risk of a 500 error and signs of outside tampering. The file is read in your browser and is not sent anywhere.
The text was pasted manually, so the byte-level checks were skipped. To see BOM, CRLF and invisible characters, drag in the file itself.
A clean .htaccess does not cure a hack. If the site is compromised, the malicious code lives in PHP and .htaccess is only its consequence: the dropper will rewrite the file back within minutes of your cleaning it. The order of work is the reverse — first find the executable code, then tidy up the config.
The source file with line numbers will appear here.
Lines with findings are marked with !: red for errors, amber for warnings. Invisible and non-printing characters are shown as a dot · — in the file itself there is nothing in their place.
Cleaning removes the BOM, converts line endings to LF, strips non-printable characters, replaces non-breaking spaces with ordinary ones and adds a trailing newline. The directives are not changed. The file is saved as htaccess-clean.txt — rename it to .htaccess before uploading it to the server.
# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<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
This is exactly what WordPress writes by itself. Put your own rules above the # BEGIN WordPress line: everything between the markers is rewritten every time you save the permalink settings.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
</IfModule>
# END WordPress
For a subdomain multisite the block is the same, but without the ^([_0-9a-zA-Z-]+/)? prefix in the last three rules: RewriteRule ^(wp-(content|admin|includes).*) $1 [L] and RewriteRule ^(.*\.php)$ $1 [L].
Replacing the block does not restore the permalinks on its own: after editing, go to Settings → Permalinks and click “Save” — WordPress will check the block and rewrite it if needed.
The file is read in your browser — its contents are never sent anywhere and never stored.
Why a file rather than pasted text
The most common cause of a 500 error after editing .htaccess is not visible in the text at all. It is the BOM — three invisible bytes at the start of the file, added by Windows Notepad when saving as UTF-8. Apache treats them as part of the first directive and cannot parse it. That is why the tool takes the file itself: only that way can the bytes be read and the BOM, the Windows-style line endings and the invisible characters inside lines be spotted. The second group of problems is directives that do nothing but look functional. mod_gzip_on is Apache 1.3 syntax; on modern servers it is silently ignored while people spend years believing compression is on. An ExpiresByType block wrapped in a check for mod_headers.c instead of mod_expires.c will not work either — and without a hint you will not notice. Third come php_value and php_flag. They work only when PHP is loaded as an Apache module. On modern hosting with PHP-FPM such a line is either ignored or produces a 500 straight away. And security separately: if the file contains rules that redirect visitors depending on which search engine they came from, or hide the redirect from the administrator, that is a classic sign of compromise. But a clean .htaccess does not cure a hack: almost always a PHP script lives somewhere in the files and will write it back.
