WordPress .htaccess: The 10 Most Useful Snippets (With Generator)
Editing .htaccess by hand is one typo away from a server error. Here are the 10 snippets that actually matter for a WordPress site – force HTTPS, redirects, caching, security headers and more – explained plainly, plus a free generator that writes them for you.
If you've ever opened your WordPress root folder over FTP, you've seen it: a small, unassuming file called .htaccess, no extension in front of the dot, easy to ignore. It looks harmless. It isn't. That one file controls how your web server handles every single request that hits your domain – and a single misplaced character in it can take your entire site offline with a blank server error 500. This guide walks through what WordPress .htaccess actually does, which parts WordPress manages for you, and the 10 snippets worth knowing, each with a ready-to-use code block. If you'd rather skip the syntax altogether, our free generator at the bottom of most sections builds all of this for you.
What .htaccess actually does (Apache and LiteSpeed)
.htaccess (short for "hypertext access") is a per-directory configuration file read by the Apache and LiteSpeed web servers – the two engines behind the large majority of WordPress hosting, including most shared hosts. Unlike a server's main configuration file, which only an administrator can edit, .htaccess lives right inside your website's folder structure and takes effect the moment you save it, no server restart required. That's exactly why it's so useful and so risky at the same time: any FTP user with write access can change how the entire server behaves for that folder, instantly, with no safety net beyond whatever backup you made yourself.
Nginx, the other major web server, doesn't read .htaccess files at all – its equivalent rules live in the main server block configuration instead. So if your host runs Nginx (some managed WordPress hosts do), the file simply won't have any effect and you'll need to ask your host to add the equivalent rules server-side. For the much larger group running Apache or LiteSpeed, though, .htaccess is the one file that quietly controls redirects, caching headers, compression, security headers, and access rules for your whole site.
The WordPress default rules – don't touch these
Every WordPress install writes its own small block into .htaccess, usually looking like this:
<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>
This block is what makes "pretty" permalinks work – it quietly routes every request that isn't an existing file or folder through index.php, letting WordPress figure out which post, page, or archive to show. WordPress regenerates it automatically whenever you save your permalink settings, and it always wraps the block in <IfModule mod_rewrite.c> markers so it can find and replace just that section. Leave it exactly where it is. Add your own snippets either above the WordPress block or below it, never inside it, so a future permalink save doesn't wipe out your custom rules along with it.
Build yours in clicks: free .htaccess generator
Skip the syntax entirely. Tick the modules you need, fill in a few values, and copy a fully commented .htaccess straight out of your browser – nothing is uploaded anywhere.
The 10 most useful WordPress .htaccess snippets
These are the rules that come up again and again on real WordPress sites – ranked roughly by how often you'll actually need them. Each one is written to work standalone; drop it above the WordPress block described earlier.
1. Force HTTPS
If your SSL certificate is active but visitors can still reach the http:// version of your site, search engines see two copies of every page and browsers won't show the padlock reliably. This rule catches any request still arriving over http and sends it to the https version with a permanent redirect:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
Use R=301, not 302 – a permanent redirect tells search engines to update their index to the https version instead of keeping the old one around. Confirm the certificate covers both www and non-www before you turn this on, or visitors on the missing variant will hit a certificate warning.
2. www to non-www (or the other way round)
Pick one canonical form of your domain and stick to it – having both example.com and www.example.com serve identical content without a redirect between them splits your SEO signals across two URLs. This snippet strips the www prefix:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]
</IfModule>
Prefer the www version instead? Flip the condition to !^www\. and prefix the target with www.. Whichever you pick, make sure it matches your WordPress "Site Address" setting and your canonical tags, or you'll end up fighting your own redirects.
3. 301 redirects for moved or renamed pages
Rename a page, merge two posts, or restructure a category and every inbound link to the old URL now points at a 404 – unless you redirect it. The simplest form maps one exact path to one destination:
Redirect 301 /old-page/ https://example.com/new-page/
For a full domain move, a RewriteRule handles the whole site in one line:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^old-domain\.com [NC]
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]
</IfModule>
This works fine for a handful of redirects, but it doesn't scale well – there's no overview of what points where, no log of the 404s you're actually generating, and no undo button beyond editing the file again. If you're managing more than a few, it's worth reading our comparison of the best free WordPress redirect plugins, or skip the file entirely and let Linkjet manage redirects comfortably from inside WordPress, with a 404 monitor and click stats included.
4. Browser caching
Every asset your site serves – CSS, JavaScript, images, fonts – gets fetched again on every single visit unless you tell the browser how long it's allowed to keep a local copy. This block sets sensible expiry windows per file type:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/css "access plus 1 week"
ExpiresByType application/javascript "access plus 1 week"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
HTML gets zero cache time on purpose – its content changes whenever you publish. Fonts get the longest window because they almost never change once deployed. Bump these numbers up if your site is mostly static, or down if you push design changes often and don't want visitors stuck looking at an old stylesheet.
5. GZIP compression
Text-based files – HTML, CSS, JavaScript, JSON, SVG – compress extremely well, often to a fraction of their original size, and every modern browser decompresses them automatically. Turning this on is close to a free performance win:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml
AddOutputFilterByType DEFLATE application/javascript application/x-javascript
AddOutputFilterByType DEFLATE application/json application/xml
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
Skip images like JPEG, PNG, or WebP here – they're already compressed formats, and running DEFLATE over them again just burns CPU for no size reduction. Many hosts enable GZIP server-wide already; if a header check tool still shows it missing, this snippet is the fix.
6. Security headers
A handful of HTTP response headers tell the browser how to treat your site defensively – whether it's allowed to be framed by another page, how much referrer data to leak to external links, and whether to trust a file's declared type instead of guessing:
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
X-Frame-Options blocks your pages from being embedded in an iframe on someone else's domain, a common trick in clickjacking attacks. X-Content-Type-Options stops the browser from second-guessing a file's declared MIME type. None of these require any configuration beyond pasting the block in – they're safe defaults for essentially any WordPress site.
7. Custom 404 page
A dead link is bad enough without a bare, unbranded server error page making it worse. This tells Apache which file to serve for any 404, instead of its generic default:
ErrorDocument 404 /404.html
In WordPress specifically, your theme's own 404.php template usually handles this already, so you rarely need the Apache-level version. It's still useful for a static section of a site, or as a safety net if something goes wrong before WordPress itself loads.
8. Hotlink protection
Hotlinking is when another site embeds an image straight from your server's URL instead of hosting a copy themselves – your bandwidth pays for their page. This rule allows your own domain to load images normally while blocking requests referred from anywhere else:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteRule \.(jpe?g|png|gif|webp|svg)$ - [F,NC,L]
</IfModule>
Swap example.com for your actual domain. The empty-referrer check in the second line matters – it keeps direct image access working for browser bookmarks, some RSS readers, and search engine image crawlers that don't always send a referrer at all.
9. Disable directory listing
If a folder on your server has no index file and directory browsing is left on, anyone who guesses or finds the folder's URL sees a raw file listing – uploads, backups, whatever's sitting there. One line turns that off everywhere the rule applies:
Options -Indexes
This is worth having even if you're confident every folder already has an index file, since a single missing one – a fresh plugin upload directory, for instance – is all it takes to expose a listing you didn't intend to show.
10. Block access to dotfiles
Files whose name starts with a dot – .env, .git, old .htaccess.bak backups – often hold configuration or credentials and have no business being reachable through a browser. This rule blocks them all, with one deliberate exception:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} "!(^|/)\.well-known/" [NC]
RewriteRule "(^|/)\." - [F]
</IfModule>
The exception carves out .well-known, a folder that has to stay public for things like SSL domain validation and Apple Pay verification files. Without that exclusion, this rule would quietly break those processes along with the security win.
Build yours in clicks: free .htaccess generator
Ten modules, plain-language descriptions, and a live preview you can copy or download – no syntax to memorize and nothing uploaded to a server.
Ten snippets cover most of what a typical WordPress site actually needs from .htaccess. Add them one at a time rather than all at once, reload the site after each save, and keep that backup within reach until you're sure everything still works. That habit alone will save you from the one scenario every WordPress owner dreads: a blank white screen and no idea which line caused it.
Frequently asked questions
Where do I find or create the .htaccess file?
It lives in your WordPress root folder – the same directory as wp-config.php and the wp-content folder – and you reach it through FTP, SFTP, or your hosting control panel's file manager. Because it starts with a dot, some file managers hide it by default; look for a "show hidden files" toggle. If the file doesn't exist yet, most hosts create it automatically the first time WordPress saves your permalink settings, or you can create an empty text file named exactly .htaccess yourself.
Why did my site show a server error 500 after editing .htaccess?
A 500 error straight after an .htaccess edit almost always means a syntax mistake – an unclosed <IfModule> tag, a missing quotation mark, or a module directive your host's server doesn't have enabled. Re-upload your backup copy over FTP to get the site back immediately, then add your new rule back in more slowly, checking the site after each small addition rather than pasting in everything at once.
Do I still need a WordPress .htaccess file if I use a caching or security plugin?
Usually yes, at least for the WordPress permalink block itself – plugins don't replace that. Caching and security plugins often add their own rules into the same file, though, so it's worth checking what a plugin has written before you add snippets manually, to avoid two sets of rules fighting each other. If a plugin already handles security headers or caching, you likely don't need the matching snippet from this list as well.
Does .htaccess work the same way on Nginx hosting?
No. Nginx doesn't read .htaccess files at all – the equivalent settings live in its main server block configuration, which only your host or server administrator can edit. If your site runs on Nginx and a snippet from this article doesn't seem to have any effect, that's the reason; you'll need to ask your host to translate the relevant rule into their Nginx config instead.
Is it safe to use a free .htaccess generator instead of writing the rules by hand?
Yes, as long as the generator runs entirely in your browser rather than sending your settings to a server – ours does, and nothing you type is uploaded anywhere. A generator mainly protects you from the two most common mistakes: mismatched <IfModule> tags and typos in a RewriteCond pattern. You should still back up your existing file before replacing it, exactly as you would with a hand-written version.