Skip to content
Server & .htaccess

WordPress Default .htaccess File: What It Contains and How to Restore It

The exact default .htaccess block WordPress writes for pretty permalinks, when WordPress recreates it automatically, and how to restore it by hand when posts 404 but the homepage still loads.

Published

WordPress’s default .htaccess file is the short RewriteEngine block the software writes into your site’s root .htaccess so permalinks like /2026/10/post-name/ resolve instead of 404ing. It looks like this:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

That is the exact block, reproduced from WordPress’s own Apache HTTP Server guide and the rewrite logic documented on the Pretty Permalinks HelpHub page. If your RewriteBase isn’t / — for example WordPress is installed in a subfolder — it will instead match that subfolder’s path, which is also normal and generated correctly by WordPress itself.

Key takeaways

  • WordPress generates this block automatically, on Apache and LiteSpeed only, whenever the file is writable and you save Settings > Permalinks.
  • If the file is missing or corrupted, every permalink except the homepage returns a 404, because only the homepage can be found without the rewrite rules.
  • Anything you or a plugin add must go above # BEGIN WordPress, never inside the markers — WordPress overwrites everything between them on every permalink save.

Need the file rebuilt with your real path and any extra rules bundled in? The WordPress .htaccess generator assembles a correct one in your browser.

What each line actually does

RewriteEngine On turns on Apache’s mod_rewrite module for this directory; without it every line below is inert.

RewriteBase / tells Apache that rewritten paths are relative to the site root. WordPress sets this to match wherever the site actually lives — a subdirectory install gets RewriteBase /blog/, not /.

RewriteRule ^index\.php$ - [L] is a no-op guard: if the request is already index.php, stop rewriting and let it through unchanged.

The two RewriteCond lines are the actual logic. %{REQUEST_FILENAME} !-f and !-d ask “does this request NOT match a real file, and NOT match a real directory?” Both have to be true for the final rule to fire — so an actual image, CSS file, or uploaded PDF is served directly and never touches WordPress’s routing.

RewriteRule . /index.php [L] is what makes permalinks work: anything that survived the two conditions above — meaning it isn’t a real file or folder — gets sent to index.php, and WordPress’s own routing (WP_Query, rewrite tags) decides what post, page, or archive that URL actually means.

When WordPress recreates this file, and when it won’t

WordPress tries to write .htaccess itself whenever you open Settings > Permalinks and click Save Changes, even if nothing changed on the screen. That save triggers flush_rewrite_rules(), which attempts to open .htaccess for writing and insert the current block between the markers.

That attempt silently fails, leaving the file missing or stale, when:

  • The file or its parent folder isn’t writable by the user PHP runs as. Many shared hosts run PHP as a different system user than the one that owns files uploaded over FTP, so file permissions that look fine in an FTP client still block WordPress from writing.
  • You’re on nginx. .htaccess is an Apache and LiteSpeed mechanism only (Apache’s own AllowOverride documentation explains why — nginx has no directory-level config file it rereads per request). The equivalent routing on nginx is a try_files directive in the server block, which only someone with server access can edit; WordPress can’t write it for you, ever.
  • AllowOverride is set to None for your site’s directory in the main Apache config. This is the setting that lets a .htaccess file override anything at all; Apache’s docs are explicit that with AllowOverride None, “then .htaccess files are completely ignored” — WordPress can write a perfect file and it will still do nothing until a host-level config change flips this to All or at least FileInfo.
  • The file was deleted or never existed and something about the save didn’t retrigger a rewrite — most often because permalinks were already set to the same structure, so WordPress saw no change to flush.

How to restore it by hand

If posts and pages 404 while the homepage still works, that’s the signature of a missing or broken .htaccess. Fix it in two steps.

1. Try the one-click fix first. Go to Settings > Permalinks in wp-admin and click Save Changes without changing anything. If the file is writable, this alone regenerates it and you’re done.

2. If that doesn’t fix it, create the file by hand. Connect over FTP/SFTP or your host’s file manager, go to the folder WordPress is installed in (the one containing wp-config.php), and check whether .htaccess exists at all — it’s a dotfile, so some file managers hide it by default; turn on “show hidden files.”

  • If it’s missing, create a new file named exactly .htaccess (no .txt, nothing before the dot).
  • Paste in the default block from the top of this guide, adjusting RewriteBase if WordPress lives in a subfolder.
  • Save, then reload a post permalink to confirm it works.

If it still 404s after that, the cause has shifted from “.htaccess is missing” to “.htaccess is being ignored” — check AllowOverride with your host, since a correct file sitting in a directory where Apache is told to ignore it behaves identically to no file at all.

Your own rules vs. WordPress’s block

A plugin or a manual edit might add rules of its own — redirects, hotlink protection, caching headers. Those are a different, separate block from the one WordPress generates, and the two should never overlap:

# Rules you or a plugin added — ABOVE the WordPress markers
<FilesMatch "\.(jpg|jpeg|png|gif)$">
    # example: hotlink protection, caching rules, etc.
</FilesMatch>

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Anything placed between # BEGIN WordPress and # END WordPress gets silently deleted the next time anyone saves the Permalinks screen, because WordPress treats that whole span as its own and rewrites it wholesale. This is the single most common cause of “my custom rule disappeared” — it was never removed on purpose, it was inside a block WordPress considers its own to manage. For redirects specifically, see WordPress .htaccess redirect rules done right for where they belong and how to avoid loops.

It’s also the most common cause of a sudden 500 Internal Server Error right after editing the file: a rule copy-pasted from a forum post written for a different Apache version (2.2 Order/Deny syntax mixed with 2.4 Require syntax) breaks the parse for the entire file, including the WordPress block beneath it, and the whole site goes down — not just the part you touched.

Beyond the default block

The default block only handles permalink routing. If you also want to tighten up access to sensitive files or add the handful of .htaccess rules that genuinely reduce attack surface — blocking PHP execution in /uploads, denying direct requests to wp-config.php — see WordPress .htaccess security rules that actually help. And if permalinks are 404ing for a reason other than a missing file — wrong permalink structure, a caching layer serving stale rules, multisite subdirectory conflicts — WordPress permalinks not working walks through the other causes.

FAQ

What is the default WordPress .htaccess file? It’s the RewriteEngine block WordPress writes between # BEGIN WordPress and # END WordPress so pretty permalinks route to index.php instead of 404ing.

What is WordPress’s exact default .htaccess code? RewriteEngine On, RewriteBase /, a pass-through rule for index.php itself, two conditions checking the request isn’t a real file or directory, and a final rule sending everything else to index.php. The full block is reproduced at the top of this guide.

Why do all my posts 404 except the homepage? The homepage can be found without any rewrite rules; every other permalink needs them. A missing or corrupted .htaccess on Apache produces exactly this pattern.

Does WordPress recreate .htaccess automatically? Only if the file is writable — resaving Settings > Permalinks triggers it. If the file isn’t writable, is missing on a host that doesn’t autogenerate it, or AllowOverride is off, WordPress can’t fix it for you and you need to create or fix the file by hand.

Why doesn’t nginx have a WordPress .htaccess file? .htaccess only works on Apache and LiteSpeed. nginx has no per-directory config file and ignores .htaccess entirely; the same routing is written as a try_files rule in the nginx server block instead.

Why did my .htaccess break after I saved permalinks? A custom rule was placed inside the # BEGIN WordPress / # END WordPress markers instead of above them, and WordPress overwrote that whole span the next time permalinks were saved.


Rebuild a clean, correct .htaccess — default permalink block plus any security or redirect rules you actually need — with the free WordPress .htaccess generator.

William Lopez

William Lopez is the founder of Odie Themes. He builds the free WordPress tools and themes on this site and has been on WordPress.org since December 2019.

WordPress.org About

FAQ

Questions

What is the default WordPress .htaccess file?

It is the short RewriteEngine block WordPress writes into the .htaccess file in your site's root folder so that pretty permalinks work. It sits between the comments # BEGIN WordPress and # END WordPress and sends any request that isn't a real file or folder to index.php, where WordPress figures out what to show.

What is WordPress's exact default .htaccess code?

RewriteEngine On, RewriteBase /, a rule that lets existing files and directories through unchanged, and a final RewriteRule that sends everything else to index.php with the query string preserved. It is reproduced in full below and matches the block WordPress itself generates on Settings > Permalinks.

Why do all my posts 404 except the homepage?

This is the classic symptom of a missing or corrupted .htaccess file on Apache. The homepage loads because the server can find index.php directly, but every other permalink needs the rewrite rules to route it there, and without them Apache just looks for a file that doesn't exist and returns a 404.

Does WordPress recreate .htaccess automatically?

Only when the file is writable and you resave Settings > Permalinks. WordPress checks whether it can write to the file and, if so, rewrites the block between its markers. If the file is missing, read-only, or owned by a different user than PHP runs as, WordPress silently fails to write it and you have to create it by hand.

Why doesn't nginx have a WordPress .htaccess file?

Because .htaccess is an Apache (and LiteSpeed) feature; nginx has no equivalent and ignores the file completely. On nginx the same routing has to be written as a try_files directive in a server block, which only your host or a sysadmin can edit, since nginx doesn't re-read per-directory config files on every request.

Why did my .htaccess break after I saved permalinks?

Almost always because a plugin or an earlier manual edit placed custom rules inside the WordPress markers instead of above them. WordPress overwrites everything between # BEGIN WordPress and # END WordPress every time permalinks are saved, so any rule placed inside is silently deleted or, if it was syntactically dependent on a neighboring line that got rewritten, left broken.