If your site went from working to a plain "500 Internal Server Error" right after you edited .htaccess, installed a plugin or changed hosting, the file is almost certainly the cause. Apache reads .htaccess on every request, so a single bad line breaks every URL under that directory at once, including the home page.
The browser will not tell you why. The Apache error log will, and it usually names the exact file, line and directive. For the general picture of 500 errors, see Fix 500 Internal Server Error; this page is only about .htaccess.
Step 1: confirm .htaccess is the cause
Rename the file and reload the page:
mv .htaccess .htaccess.off
curl -I https://example.com/
If the status changes from 500 to 200 (or to a 404 on pretty URLs), you have your answer. Keep the old file as .htaccess.off so you can inspect it. On shared hosting without a shell, rename it in the file manager. Confirm the result with the HTTP Status Checker.
Step 2: read the error log
Typical locations are /var/log/apache2/error.log on Debian and Ubuntu, /var/log/httpd/error_log on RHEL-family systems, and a per-account error_log on many control panels.
sudo tail -n 30 /var/log/apache2/error.log
The entries you want look like these:
/var/www/html/.htaccess: Invalid command 'php_value', perhaps misspelled or defined by a module not included in the server configuration
/var/www/html/.htaccess: RewriteCond: bad flag delimiters
/var/www/html/.htaccess: Options not allowed here
Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary.
Match your line to one of the causes below.
Common causes
Invalid command
The directive belongs to a module that is not loaded, or it is misspelled. This is the most common case, and it has its own page: Apache Invalid command in .htaccess.
Syntax error in a directive
Typical mistakes are an unclosed <IfModule>, a missing space before a flag list, or smart quotes pasted from a blog post.
# Wrong: no space before the flags
RewriteRule ^old$ /new[R=301,L]
# Right
RewriteRule ^old$ /new [R=301,L]
Check the file for non-ASCII quotes with grep -nP '[^\x00-\x7F]' .htaccess.
The directive is not allowed in .htaccess
The AllowOverride setting of the parent Directory block decides what an .htaccess file may contain. If it is None or lists only some groups, a directive from another group raises "not allowed here". Server-level settings such as ServerName, Listen or <VirtualHost> never work in .htaccess. On a server you control:
<Directory /var/www/html>
AllowOverride All
</Directory>
Use AllowOverride All only where you trust the content, and use narrower groups (FileInfo Indexes Options=...) where you can.
Rewrite requires FollowSymLinks
If the log says Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden, add this at the top of the file:
Options +FollowSymLinks
PHP settings that do not apply
php_value and php_flag only work when PHP runs as an Apache module (mod_php). Under PHP-FPM or CGI they cause a 500. Move those settings to .user.ini or php.ini instead.
Redirect loop
"Request exceeded the limit of 10 internal redirects" means a rewrite rule matches its own output. The usual fix is a condition that excludes the target, for example RewriteCond %{REQUEST_URI} !^/index\.php. For browser-side loops, see ERR_TOO_MANY_REDIRECTS.
File permissions
An .htaccess that Apache cannot read can also produce a 500 or 403. Typical safe values are 644 for the file and 755 for directories, with the owner your deploy user.
Step 3: validate before you reload
If you have shell access and the rules live in a vhost rather than .htaccess, test the config before applying it:
sudo apachectl configtest
This does not parse .htaccess files, because those are read per request. That is why a bad .htaccess fails live. Prefer putting rules in the virtual host config when you can (with AllowOverride None), which is both safer and faster.
Step 4: bisect
For a long file, comment out half of it, reload, and repeat. A few minutes of halving finds the offending line, especially in files appended to by several plugins.
How to verify
After the fix, request a few URL types and compare status codes: the home page, a pretty URL, a static file and a 404 path. The HTTP Header Checker shows the final status and headers, and the Redirect Checker confirms any rewrite rules still redirect as intended. Put an Uptime Monitor on the home page so the next bad edit alerts you quickly.
Next steps
- Read Fix 500 Internal Server Error for causes beyond .htaccess.
- Handle the module case in Apache Invalid command in .htaccess.
- Debug rewrites with Apache mod_rewrite not working.
- Look up the HTTP 500 reference.
FAQ
Why does my whole site break from one .htaccess line?
Apache parses the file on every request to that directory tree, and a configuration error aborts the request with 500. Every URL below the file is affected.
Where is the Apache error log?
Usually /var/log/apache2/error.log on Debian-based systems and /var/log/httpd/error_log on RHEL-family systems. Hosting panels often show a per-site log in the control panel.
Can I test .htaccess changes safely?
Edit a copy, keep the working version beside it, and test with curl -I. Making changes during low traffic and keeping a one-command rollback is the practical safety net.
Does the nginx server read .htaccess?
No. nginx ignores .htaccess entirely, so rules must be rewritten as nginx config.
Get notified when this fix updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.