Skip to content

The Default WordPress .htaccess File and How to Restore It

8 min read

Applies to: WordPress 7.1.3 on Apache 2.4 (tested with WP-CLI 2.12.0 on Debian 13), LiteSpeed Cache 7.9.1

The default WordPress .htaccess file holds one block of rewrite rules that sends every request for a page that is not a real file or folder to index.php. That is what makes "pretty" permalinks such as /sample-post/ work on Apache and LiteSpeed. To restore it, replace everything between # BEGIN WordPress and # END WordPress with the block below, or open Settings > Permalinks in WordPress and click Save Changes so WordPress writes it again.

The default WordPress .htaccess block

This is exactly what WordPress 7.1.3 wrote to a new single-site install in our lab (Post name permalinks, WordPress in the web root):

# 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

The WordPress developer documentation shows the same rewrite lines without the comment lines and without the <IfModule mod_rewrite.c> wrapper. The rules are identical. The wrapper only tells Apache to skip the block when the mod_rewrite module is not loaded, so we recommend keeping it.

What each line does:

  • RewriteEngine On turns on mod_rewrite for this folder.
  • RewriteRule .* - [E=HTTP_AUTHORIZATION:...] passes the HTTP Authorization header on to PHP. WordPress added it in version 5.6 for application passwords, because servers that run PHP as CGI or FastCGI do not pass that header on their own.
  • RewriteBase / is the URL path of the WordPress install.
  • RewriteRule ^index\.php$ - [L] stops processing when index.php itself is requested.
  • The two RewriteCond lines check that the request is not an existing file (!-f) or folder (!-d), so images, CSS and wp-admin are served directly.
  • RewriteRule . /index.php [L] hands every other request to WordPress, which works out which post or page to show.

Where the .htaccess file is

The file sits in the folder WordPress is installed in, next to wp-config.php, wp-admin and wp-content. On a cPanel account that is usually public_html for the main domain. The name starts with a dot, so it is hidden: in cPanel File Manager turn on hidden files first (see how to edit .htaccess in cPanel File Manager).

If WordPress runs in a subfolder, the file lives in that subfolder and the paths change. With the site address set to http://example.com/blog, WordPress wrote these two lines instead (the rest of the block was the same):

RewriteBase /blog/
RewriteRule . /blog/index.php [L]

If permalinks are set to Plain (?p=123 links), WordPress needs no rewrite rules. In our test it left only the marker and comment lines, with nothing between them.

How to restore the WordPress .htaccess file

Method 1: let WordPress write it (easiest)

  1. Log in to WordPress and open Settings > Permalinks.
  2. Do not change anything. Click Save Changes.
  3. If the file (or, when it does not exist, the folder) is writable, WordPress writes its block and shows "Permalink structure updated."
  4. If it is not writable, WordPress 7.1.3 shows "You should update your .htaccess file now." and, at the bottom of the page, an error that the file "is not writable" followed by a box with the rules. Copy them and use method 2.

Method 2: paste the block by hand

  1. Download or copy the current .htaccess first, for example as .htaccess.bak, so you can go back.
  2. Open .htaccess in cPanel File Manager or over SFTP. If the file does not exist, create it in the WordPress folder.
  3. Delete only the lines from # BEGIN WordPress to # END WordPress and paste the default block above in their place. If WordPress is in a subfolder, change RewriteBase and the last RewriteRule to match.
  4. Leave blocks written by other plugins (caching, security, redirects) and your own rules where they are.
  5. Save the file and open the home page and one post in a private browser window.

Method 3: WP-CLI

On a VPS or any host with SSH, run wp rewrite flush --hard in the WordPress folder. In our test this command did not create the file at first; it only printed "Warning: Regenerating a .htaccess file requires special configuration. See usage docs." As the WP-CLI documentation explains, you must first tell WP-CLI that mod_rewrite is loaded, with a wp-cli.yml file in the WordPress folder:

apache_modules:
  - mod_rewrite

Then wp rewrite flush --hard printed "Success: Rewrite rules flushed." and wrote the block shown above. One catch from our lab: when the web server user could not write to the file, WP-CLI still printed "Success" but left the file unchanged. Always open the file afterwards to check. According to the WP-CLI documentation, --hard works only on single-site installs.

Keep your own rules outside the markers

WordPress only manages the lines between its own markers. In our test we added Options -Indexes above the block and broke the last rewrite line inside it. After a flush, WordPress put its own rules back and kept our line untouched. So:

  • Put custom rules (redirects, HTTPS, security headers) above # BEGIN WordPress, so they run before WordPress hands requests to index.php.
  • Never edit inside the WordPress markers: the next permalink save overwrites it.
  • Plugins add their own marked blocks. LiteSpeed Cache 7.9.1, for example, writes # BEGIN LSCACHE and # BEGIN NON_LSCACHE blocks at the top of the file when it is activated or its settings are saved, removes them when it is deactivated, and saves a copy of the old file as .htaccess.bk the first time it changes it.

WordPress Multisite .htaccess

Multisite uses different rules, and WordPress does not write them for you: the code that saves .htaccess stops on a multisite install. Copy the rules that WordPress shows on the Tools > Network Setup screen when you create the network, or use the version for your network type from the WordPress documentation. The subfolder version for WordPress 3.5 and later is:

# BEGIN WordPress Multisite
# Using subfolder network type: https://wordpress.org/documentation/article/htaccess/#multisite

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]

# END WordPress Multisite

For a subdomain network, the wp-admin rule becomes RewriteRule ^wp-admin$ wp-admin/ [R=301,L] and the two lines before the last become RewriteRule ^(wp-(content|admin|includes).*) $1 [L] and RewriteRule ^(.*\.php)$ $1 [L]. Networks created with WordPress 3.4 or older need the older rules with the ms-files.php line, also on the WordPress page.

When .htaccess changes do nothing

  • Apache ignores the file: Apache reads .htaccess only where AllowOverride allows it, and its default is None. Rewrite rules need at least AllowOverride FileInfo plus Options FollowSymLinks (or SymLinksIfOwnerMatch), according to the Apache documentation. On Debian 13 (Apache 2.4.68) the stock config sets AllowOverride None for /var/www/ and mod_rewrite is off until you run a2enmod rewrite and restart Apache. A quick test from the Apache documentation: add a nonsense word such as TestMe on its own line and reload the page. If you do not get an HTTP 500 error, Apache is not reading the file. Remove the word again afterwards.
  • LiteSpeed: LiteSpeed Web Server supports .htaccess, according to LiteSpeed. OpenLiteSpeed reads only the rewrite rules and, according to its documentation, must be restarted after you change them.
  • Nginx: Nginx has no .htaccess at all. WordPress on Nginx needs try_files $uri $uri/ /index.php?$args; in the server block instead.
  • 500 error right after an edit: a typo or a directive that is not allowed in .htaccess makes Apache return HTTP 500 for the whole site. The web server error log names the problem line. Put your backup copy back, then add your changes one at a time.

If you would rather not manage Apache settings yourself, our cPanel web hosting runs on LiteSpeed, which supports .htaccess files.

Related articles: what is .htaccess and how to edit it in cPanel, force HTTPS for WordPress with .htaccess, how to set up redirects in WordPress, leverage browser caching with .htaccess in WordPress.

Official documentation: WordPress: Apache HTTPD and .htaccess, wp rewrite flush, Apache AllowOverride.

Related services

Web hosting

shared hosting on Virtualmin with NVMe storage, free SSL and email.

Managed cPanel VPS

cPanel included; we handle updates, security and monitoring.

Hire an expert

engineers per 15 minutes, per hour or per month, with no contract.

Was this answer helpful?

Still stuck? Open a ticket