Solved.tools โ€” Free Online Calculators & Tools

We use cookies for analytics and advertising. Learn more about our cookie policy

.htaccess Generator

Last updated: 23 August 2026

Reviewed by Gavin ยท Research and drafting assisted by AI

Directives

Toggle the rules you want. 6 of 12 sections enabled.

Redirect every http:// request to https:// with a permanent 301 redirect.
Redirect example.com โ†’ www.example.com to consolidate host canonicalisation.
Redirect www.example.com โ†’ example.com, the modern canonical form.
Redirect /about/ โ†’ /about so URLs are canonical without a trailing slash.
Send unknown paths to index.html so single-page apps handle the route.
Block other sites from embedding your images by inspecting the Referer header.
Choose the file Apache serves when a directory is requested (default: index.html).
Stop Apache listing files when no index file is present.
Serve friendly 404 / 403 / 500 pages instead of the Apache default.
Set far-future Expires headers for static assets to enable 1-year caching.
Compress text responses on the fly with mod_deflate to shrink transfer size.
Deny web access to common secrets and VCS directories using FilesMatch.

Custom 301 / 302 redirects

1 active redirect. Empty rows are skipped.

Generated .htaccess

# Generated .htaccess โ€” reviewed at https://solved.tools/tools/htaccess-generator
# Generated: 2026-08-24T05:11:33.646Z

# Force HTTPS
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# Strip www prefix
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
  RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
</IfModule>

# Disable directory browsing
Options -Indexes

# Browser caching via mod_expires
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpeg        "access plus 1 year"
  ExpiresByType image/png         "access plus 1 year"
  ExpiresByType image/gif         "access plus 1 year"
  ExpiresByType image/webp        "access plus 1 year"
  ExpiresByType image/svg+xml     "access plus 1 year"
  ExpiresByType image/x-icon      "access plus 1 year"
  ExpiresByType text/css          "access plus 1 month"
  ExpiresByType application/javascript "access plus 1 month"
  ExpiresByType application/x-javascript "access plus 1 month"
  ExpiresByType text/javascript   "access plus 1 month"
  ExpiresByType text/html         "access plus 0 seconds"
  ExpiresByType application/pdf   "access plus 1 month"
  ExpiresByType font/woff2        "access plus 1 year"
  ExpiresByType font/woff         "access plus 1 year"
  ExpiresDefault                  "access plus 1 month"
</IfModule>

# GZIP compression via mod_deflate
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/json
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/atom+xml
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE font/otf
  <IfModule mod_setenvif.c>
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
</IfModule>

# Block access to sensitive files
<FilesMatch "^\.(env|git|htaccess|htpasswd)">
  Require all denied
</FilesMatch>
<FilesMatch "(^|/)\.git(/|$|\.)">
  Require all denied
</FilesMatch>

Every mod-dependent block is wrapped in an <IfModule> guard so it is safe to install even if a particular Apache module is not loaded. Always back up your existing .htaccess before deploying.

Was this helpful?


Introduction

The .htaccess file is one of the most powerful and most misunderstood files on a typical Apache web server. It is a per-directory configuration file: place it inside any folder served by Apache and the directives inside it apply to that folder and every subdirectory beneath it. There is no formal schema and no compiler, every line is read by Apache at request time, parsed top to bottom, and matched against the incoming request. That directness is exactly what makes it both useful (no server restart needed, just upload and the next request picks it up) and dangerous (a typo or an infinite rewrite loop can take a site offline in seconds).

This tool generates a complete .htaccess file from a set of common toggles: force HTTPS, canonicalise the WWW prefix, set up custom 301 and 302 redirects, disable directory browsing, serve custom error pages, enable browser caching via mod_expires, enable on-the-fly compression via mod_deflate, block hotlinking of images, deny access to sensitive files such as .env and .git, normalise trailing slashes, and rewrite unknown paths to index.html for single-page applications. Every mod-dependent block is wrapped in an <IfModule mod_*.c> guard so it is safe to install the file even on Apache builds that have a different module set loaded.

The output is a plain text file. You copy it, paste it into a file called .htaccess at the root of the directory you want to protect, and Apache takes care of the rest. The tool runs entirely in your browser, no upload, no server-side processing, no account required.

How to Use

The interface has two columns. On the left are the toggles and inputs that control which directives appear in the output. On the right is the live-generated .htaccess text, with a Copy button in the top-right corner.

  1. Tick the boxes for the rules you want to include. The generator begins with a small default set enabled: force HTTPS, strip the WWW prefix, disable directory browsing, enable browser caching, enable GZIP compression, and block access to sensitive files. Disable anything you do not want.
  2. Fill in the custom inputs when they appear. The "Directory index" section exposes a text field for the index filename (index.html by default). The "Custom error pages" section exposes three text fields for the 404, 403 and 500 paths.
  3. Edit the "Custom 301 / 302 redirects" rows at the bottom of the left column. Each row has a code selector (301 or 302), a from-path, a to-path, and a remove button. Empty rows are skipped silently. Use the "Add redirect" button to add more rows.
  4. Watch the right-hand panel update as you change anything. The generator is fully reactive, there is no Apply button.
  5. Click Copy to copy the entire output to your clipboard, then paste it into a file named .htaccess at the root of the directory you want to configure. Apache reads the file on the next request.
  6. Before deploying, back up the existing .htaccess. If you are replacing a live configuration, save the old file so you can roll back in seconds if a rule misbehaves.

The Reset button at the bottom-left restores the default toggles and clears the redirect rows.

The Directives Explained

mod_rewrite

mod_rewrite is the workhorse of .htaccess rules. It maps incoming URLs to other URLs using a pattern engine that supports wildcards, character classes, back-references and condition chains. The generator wraps every rewrite block in <IfModule mod_rewrite.c> so the file is safe to install on hosts that do not have mod_rewrite loaded.

The HTTPS-redirect block uses one of the canonical patterns from the Apache documentation: RewriteEngine On turns the engine on, RewriteCond %{HTTPS} off only matches requests that are not already HTTPS, and RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] sends them to the same host and path on HTTPS with a permanent 301 status and the [L] flag to stop further rewriting.

The WWW canonicalisation blocks use a similar pattern. The add-www variant matches any host that does not begin with www. and redirects to the www-prefixed equivalent. The strip-www variant matches hosts that do begin with www. and redirects to the bare domain. Pick one, never both, or you will create a redirect loop.

The hotlink protection block inspects HTTP_REFERER and rejects any request for an image whose referer is not your own domain. It uses the [F] flag to send a 403 Forbidden response. Be aware that hotlink protection can interfere with browsers and security tools that strip referer headers, and that legitimate services such as RSS readers and link previewers may break as a side effect.

The SPA front-controller pattern is the standard rewrite rule used by React, Vue and Angular SPAs: if the requested path does not correspond to an existing file (!-f) and is not an existing directory (!-d), serve index.html and let the client-side router handle the route. Without this rule, refreshing a deep link returns a 404.

mod_expires

mod_expires tells browsers and CDNs how long to cache a response before revalidating with the origin. The generator emits a block that uses ExpiresByType to set per-MIME-type lifetimes: one year for image formats, fonts and favicons; one month for CSS, JavaScript and PDF; zero seconds for HTML so dynamic pages always revalidate.

Cache times that are too aggressive cause problems when an asset changes but the cached copy is still fresh in the browser. The standard solution is filename fingerprinting (e.g. style.abc123.css) so the URL itself changes whenever the content changes, which lets you set a one-year expiry without worrying about stale assets.

mod_deflate

mod_deflate compresses responses on the fly before they leave the server. The generator emits AddOutputFilterByType DEFLATE directives for text-based MIME types (HTML, plain text, XML, CSS, JavaScript, JSON, SVG) and font types (TTF, OTF). The inner <IfModule mod_setenvif.c> block excludes very old browsers (Netscape 4 and early Internet Explorer) that had broken GZIP support.

Note that mod_deflate is the legacy name for this filter in Apache 2.0 and 2.2. In Apache 2.4 the module was renamed to mod_filter with DEFLATE as the filter name. The directive still works because Apache maintains backward compatibility, but on modern installs you may see advice to use FilterProvider and FilterChain instead.

FilesMatch

<FilesMatch> is a core Apache directive, not a module. It applies a block of directives to any file whose name matches a regular expression. The generator uses it to deny access to dotfiles that should never be web-accessible: .env, .git, .htaccess, .htpasswd. The Require all denied directive works on Apache 2.4; on Apache 2.2 you would need Order allow,deny and Deny from all instead.

The regex ^\.(env|git|htaccess|htpasswd) matches any filename that begins with a dot followed by one of those names. Be careful with the regex: the dot must be escaped (\.) or it will match any character. The generator does this correctly.

DirectoryIndex, Options and ErrorDocument

These are core Apache directives, not modules. DirectoryIndex tells Apache which file to serve when a directory is requested (the default is index.html, but index.php is also common). Options -Indexes disables directory listings, so an Apache directory with no index file returns 403 Forbidden instead of listing every file in the folder. ErrorDocument lets you point a given HTTP status at a custom page.

Worked Examples

Example 1, A static portfolio site that needs HTTPS, no www, gzip and caching.

Open the tool. The defaults already enable Force HTTPS, Strip WWW, Disable directory browsing, Browser caching, GZIP compression, and Block sensitive files. The generated config contains:

# Force HTTPS
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# Strip www prefix
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
  RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
</IfModule>

Then the Options -Indexes, the mod_expires block with one-year caching for images and one-month for CSS, and the mod_deflate block for HTML/CSS/JS compression. Drop the file into the web root and the site loads over HTTPS, redirects any leftover www. URLs, and serves compressed and cacheable assets.

Example 2, A CMS migration that needs custom 301 redirects for renamed pages.

Disable Force HTTPS temporarily. Enable the "Custom 301 / 302 redirects" section and add a row for each old URL: from /about-us to /about, code 301; from /blog/2024/* to /blog (note that wildcards need a RewriteRule, not a Redirect, so this particular row would not work, change the strategy). The simple /about-us row generates:

# Custom redirects
Redirect 301 /about-us /about

The Redirect directive is from mod_alias, not mod_rewrite, and it handles straightforward prefix matches cleanly. For pattern-based redirects you need RewriteRule, which is more powerful but more error-prone.

Example 3, A React single-page app deployed to a subdirectory.

Enable the SPA front-controller toggle. The generator emits a rewrite block that sends any unknown URL to /index.html:

# SPA front-controller fallback
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.html [L]
</IfModule>

The !-f and !-d conditions make sure existing files and directories are still served directly, only requests for paths that do not exist fall through to index.html, where the React Router takes over and renders the right view.

Example 4, An image-heavy blog that needs hotlink protection.

Enable Hotlink protection. The generator emits a rewrite block that intercepts requests for common image extensions when the referer is not your own domain:

# Hotlink protection
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_REFERER} !^$
  RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
  RewriteRule \.(jpg|jpeg|png|gif|webp|svg)$ - [F,L]
</IfModule>

Edit the example.com host to match your real domain. The first RewriteCond allows requests with no referer at all (some browsers strip it for privacy; some image proxies send no referer). The second RewriteCond allows requests from your own domain. The third line forbids (the [F] flag) any image request that does not match one of those two conditions.

Example 5, A Node app behind a reverse proxy that needs to block .env files.

The defaults already enable Block sensitive files. The generator emits:

<FilesMatch "^\.(env|git|htaccess|htpasswd)">
  Require all denied
</FilesMatch>
<FilesMatch "(^|/)\.git(/|$|\.)">
  Require all denied
</FilesMatch>

The first pattern blocks any file whose name starts with a dot followed by one of those names. The second pattern is a stricter guard for .git directories, because some attackers will try to fetch .git/HEAD or .git/config even if a simple dotfile blocklist misses them.

Where It Shows Up

.htaccess is Apache's per-directory configuration file, so it shows up on any host that runs Apache: traditional LAMP stacks (Linux, Apache, MySQL, PHP), cPanel and Plesk shared hosting, WordPress and Drupal installations, Magento and other PHP ecommerce platforms, and many corporate intranets. It also appears on hosting providers that hide Apache behind a panel: DreamHost, Bluehost, SiteGround, HostGator, A2 Hosting and many others let you edit .htaccess either through a file manager or a control-panel button.

Some hosts run Apache in front of a Node.js, Python or Ruby backend. The .htaccess file in those setups typically only handles the static-asset URLs and routes everything else through a proxy (ProxyPass). The SPA front-controller pattern in this generator is appropriate for those setups as long as the actual HTML is served by Apache.

Cloudflare Workers, Netlify and Vercel do not use .htaccess at all, they have their own configuration systems (_redirects, vercel.json, wrangler.toml). If you are deploying to one of those platforms, use their native redirect and header configuration instead.

Common Mistakes

Rule ordering. Apache reads the file top to bottom, so the order of your rules matters. A redirect that fires before a rewrite block can produce surprising behaviour. Place canonical host and protocol rules first, then pattern-based rewrites, then per-directory settings.

Missing RewriteBase. On some shared hosts, RewriteRule patterns need an explicit RewriteBase / to anchor them correctly. The generator omits it by default because most modern Apache configurations do not need it, but if your rules behave unexpectedly, add RewriteBase / immediately after RewriteEngine On.

Infinite redirect loops. Combining Force HTTPS with Strip WWW, or with a CDN that already rewrites HTTPS, can produce a loop where the browser sees two 301s and never arrives at the final URL. Test combinations on a staging host before deploying to production.

AllowOverride None. Apache's central configuration can disable .htaccess entirely with AllowOverride None in the main server config or a <Directory> block. If your file is being silently ignored, check the Apache error log for ".htaccess:...not allowed here", that message means AllowOverride is set too restrictively for the directory you are configuring. Talk to your hosting provider if you cannot change this yourself.

Caching too aggressively. Setting ExpiresByType text/html "access plus 1 year" is a recipe for stale content. HTML responses should always revalidate ("access plus 0 seconds"), while truly static assets such as fingerprinted images and font files can safely cache for a year or more.

mod_rewrite disabled. The generator wraps every RewriteRule block in <IfModule mod_rewrite.c>, but if your host has mod_rewrite disabled and you try to use redirects anyway, nothing will happen. Check phpinfo() if you have PHP, or ask your host.

Frequently Asked Questions

What is the .htaccess file and where does it go?

.htaccess (short for "hypertext access") is a per-directory configuration file that Apache reads on every request. Place it at the root of the directory you want to configure, typically the document root of your site, which is the same folder that contains your index.html. Apache applies its directives to that directory and every subdirectory beneath it. Files in nested directories can override or extend the rules with their own .htaccess files.

Why is my .htaccess file being ignored?

Three common causes. First, Apache might be configured with AllowOverride None for your directory, which disables per-directory config files entirely, check the Apache error log for "not allowed here" messages. Second, the file might not be named exactly .htaccess (no extension, lowercase, dot at the start). Third, your FTP client might be hiding dotfiles by default; enable "show hidden files" in the client to see it.

Can I use this generator on shared hosting?

Yes. .htaccess is the standard configuration mechanism on cPanel, Plesk, and most shared hosting providers. The generator wraps every mod-dependent block in <IfModule> guards so it is safe to install even on hosts with a different module set loaded. If a particular rule does not seem to fire, check whether the corresponding Apache module is enabled on your host.

Do I need to restart Apache after uploading?

No. Apache reads .htaccess on every request, so the new rules take effect on the very next request after the file is uploaded. There is no restart required, which is one of the reasons .htaccess is so convenient, and also one of the reasons a bad rule can take a site offline instantly.

What is the difference between 301 and 302 redirects?

301 is "Moved Permanently", it tells browsers and search engines that the old URL should be replaced by the new URL forever. Search engines transfer the SEO value from the old URL to the new one. 302 is "Found" (formerly "Moved Temporarily"), it tells them the move is temporary, so the old URL keeps its SEO value and the new URL is not indexed as the primary copy. Use 301 for permanent moves and 302 only when you intend to revert.

How do I test my .htaccess before deploying it?

Three reliable approaches. First, copy the live site to a staging host and deploy there. Second, use a local Apache install via Docker or a VM and reload the file in a controlled environment. Third, run Apache's config test command, on Debian/Ubuntu systems that is apache2ctl configtest, which parses the entire configuration including any .htaccess files Apache would load on startup. A syntax error in your .htaccess is logged but does not stop Apache from running.

Can I use .htaccess with Nginx?

No. Nginx does not support .htaccess files at all, per-directory configuration is a core Apache feature, and Nginx deliberately omits it for performance reasons. If you need equivalent functionality on Nginx, edit the server block in your nginx.conf and reload Nginx. The directives are similar but not identical, so a direct copy will not work.

Is .htaccess slow?

In theory, yes, Apache parses every .htaccess file in every directory from the document root down to the requested file on every request. In practice, the overhead is small for most sites because Apache caches the parsed configuration in memory. If you serve enough traffic that the overhead matters, the fix is to move your rules into the main server configuration and set AllowOverride None for your document root.

References

  • Apache HTTP Server Documentation, Version 2.4, mod_rewrite chapter. The official reference for RewriteRule, RewriteCond, the [L], [R], and [F] flags, and the canonical HTTPS-redirect pattern.
  • Apache HTTP Server Documentation, Version 2.4, mod_expires chapter. The reference for ExpiresActive and ExpiresByType and the recommended lifetimes for static MIME types.
  • Apache HTTP Server Documentation, Version 2.4, mod_deflate chapter. The reference for AddOutputFilterByType DEFLATE and the mod_setenvif block that excludes old browsers.
  • Apache HTTP Server Documentation, Version 2.4, core AllowOverride directive. Explains when .htaccess files are honoured and when they are silently ignored.
  • MDN Web Docs, HTTP caching overview. The client-side companion to the Apache directives, covering Cache-Control, ETag, and the validation model that makes caching work.