
🚀 How to remove index.php and index.html from URL: 301 redirect to the site root
You open Google Search Console and see the homepage indexed twice: as site.ru/ and as site.ru/index.php. Or site.ru/index.html. For a search engine, these are two different URLs with identical content. The result: the page's authority is split in half between the duplicates, rankings drop, and crawl budget goes to waste.
The problem is as old as the web. The mechanics are simple: by default, the server returns index.html or index.php when requesting the root via the DirectoryIndex directive, but it doesn't block direct access to site.ru/index.php. From Apache's perspective, both addresses are legitimate. But the search engine sees two different pages with identical content and starts guessing which one to rank.
Below are three ways to set up a 301 redirect from index files to the root: from the universal .htaccess to Cloudflare and Nginx. Plus a verification method that takes two minutes.
💡 Quick overview:
- Add
mod_rewriterules to.htaccessto intercept requests toindex.htmlandindex.php - For WordPress and CMS, use a PHP redirect in the entry
index.php(it survives permalink updates) - Verify the result via
curl -Iorredirectchecker.com(the response should be301 Moved Permanently) - Go through internal site links and replace
/index.phpwith/in menus, logos, and widgets
Why index file duplicates harm your site
When a visitor types site.ru in the address bar, Apache silently substitutes index.html or index.php according to DirectoryIndex. The browser displays the page, the address stays clean, and the user doesn't notice the substitution.
But if a link to the full path site.ru/index.php already exists somewhere out there, the search crawler follows it, sees the same content as on site.ru/, and records a duplicate. Where does such a link come from? There are plenty of options: an old post on a third-party site, a partner who listed the wrong URL, a social sharing plugin that generated a share with index.php in the tail, or even the developer who added href="/index.html" in the navigation during layout.
What we get in practice:
- Split link equity. Backlinks are distributed between
/and/index.phpinstead of accumulating on a single canonical page. - Wasted crawl budget. The bot spends time crawling duplicates instead of useful sections of the site.
- Diluted relevance. The search engine doesn't understand which of the two pages to show in results and may alternate between them, user behavior statistics get skewed, and rankings become unstable.
The situation is fully manageable. It's solved by setting up a permanent 301 redirect from index.html and index.php to the root /. Let's explore the available methods.
Method 1: Redirect via.htaccess on Apache
The .htaccess file is located in the site root. If it doesn't exist, create a text file with a dot at the beginning of the name; any FTP client or hosting file manager can handle this.
Open .htaccess and find the line RewriteEngine On. If it's not there, add it as the very first line after any comments. It enables the mod_rewrite module responsible for all redirects.
Below RewriteEngine On, add the rules. Here's a minimal working set:
1 RewriteEngine On 2 3 RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/ 4 RewriteRule ^index\.php$ https://%{HTTP_HOST}/ [R=301,L] 5 6 RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.html\ HTTP/ 7 RewriteRule ^index\.html$ https://%{HTTP_HOST}/ [R=301,L]
How this works line by line:
RewriteCond %{THE_REQUEST}checks the original request string sent by the browser to the server. It explicitly contains/index.phpor/index.html, which is exactly what we're catching.RewriteRuleredirects the request to the domain root with a301code (permanent redirect). TheLflag (last) stops further rule processing.%{HTTP_HOST}automatically substitutes the site domain; you don't need to type it manually. The protocol is explicitly specified ashttps://.
Critical note: do not use the simplified construct Redirect 301 /index.php /. The Redirect directive from mod_alias loops on index files. After redirecting to /, Apache again substitutes index.php via DirectoryIndex, the rule triggers again, and the browser throws an infinite loop error. The RewriteCond + RewriteRule combination via mod_rewrite analyzes specifically the original request (%{THE_REQUEST}), not the one rewritten by internal rules, so no looping occurs.
Changes in .htaccess take effect instantly; Apache rereads the file with each request, and no server restart is required.
Method 2: PHP redirect for WordPress and CMS
On sites running WordPress, Joomla, Drupal, and other CMS platforms, editing .htaccess is risky: the CMS rewrites it when updating permalinks, changing URL structure, or activating SEO plugins. Your rules may disappear on the next settings save.
For WordPress, there's a more resilient approach: a redirect directly in the entry file index.php. It's located in the CMS installation root and executes with every request, before the core loads.
Open the WordPress index.php and add at the very beginning, right after the opening <?php tag:
1 <?php 2 // 301 redirect from index.php to root 3 if ($_SERVER['REQUEST_URI'] === '/index.php') { 4 header('Location: /', true, 301); 5 exit(); 6 } 7 8 // Standard WordPress code follows 9 define('WP_USE_THEMES', true); 10 // ...
For sites on pure PHP without a CMS, the logic is the same: place the code in the entry index.php in the public directory root. If your site uses both index files (index.php and index.html), add a similar check for index.html at the beginning of the same script.
Why this method is more reliable than editing .htaccess for CMS:
- The code lives inside a PHP file that the CMS doesn't touch when updating permalink settings.
- The
$_SERVER['REQUEST_URI']check catches specifically the requested URL, not the one rewritten by WordPress internal rules. exit()guarantees execution stops; not a single line beyond it will run.
On high-traffic projects, the PHP redirect is slightly faster than the .htaccess variant: mod_rewrite doesn't spin up to parse regular expressions, saving milliseconds on each request.
Method 3: Cloudflare, Nginx, and other servers
Cloudflare. If your site runs through Cloudflare, you can set up the redirect at the CDN level without touching server files at all. Go to Rules → Redirect Rules and create a rule:
- Field:
URI Path - Operator:
equals - Value:
/index.php - Redirect URL:
https://yourdomain.com/ - Status code:
301
Add a similar rule for /index.html. The advantage: the redirect fires on Cloudflare edge servers, and the request never even reaches your hosting. The downside: the domain must be delegated to Cloudflare NS.
Nginx. Sites on Nginx don't use .htaccess. Rules are added to the server configuration file, usually /etc/nginx/sites-available/yourdomain:
1 location = /index.php { 2 return 301 https://yourdomain.com/; 3 } 4 5 location = /index.html { 6 return 301 https://yourdomain.com/; 7 }
After editing, check the syntax with nginx -t and apply the changes: systemctl reload nginx.
LiteSpeed / OpenLiteSpeed. The server supports .htaccess with the same mod_rewrite rules as Apache; method 1 works without changes. Additionally, you can use the built-in redirect mechanism in the LiteSpeed WebAdmin panel.
IIS (Windows Server). For sites on IIS, the redirect is configured via the URL Rewrite module in web.config:
1 <rule name="Redirect index.php to root" stopProcessing="true"> 2 <match url="^index\.php$" /> 3 <action type="Redirect" url="/" redirectType="Permanent" /> 4 </rule>
Add a similar rule for index.html.
How to verify the redirect works
The most reliable method is the command line. Run:
1 curl -I https://yourdomain.com/index.php
The first line of the response should be HTTP/1.1 301 Moved Permanently, and the Location header should show the site root. Repeat for index.html. The homepage at root / should respond with code 200.
Alternative verification tools:
- Redirect Checker (redirectchecker.com) shows the full redirect chain with response codes, convenient for quick diagnostics without a terminal.
- Google Search Console → URL Inspection (the inspect and test tool): shows how Googlebot sees the page after the redirect and whether it's available for indexing.
After setting up the redirect, it's critical to check your site's internal links. Make sure menus, the logo (which usually links to the homepage), breadcrumbs, and related posts blocks point to /, not /index.php. A single broken internal link can recreate the duplicate you just removed. Do a source code search across the site: open any page, press Ctrl+U, and search for href="/index.php" or href="/index.html". Replace each occurrence with href="/".
Video: a short explanation of 301 redirects from Google
A four-minute video from Google Search Central, essential viewing if you're setting up redirects for the first time. John Mueller explains how the search engine processes permanent redirects and whether there's a limit on their number:
⁉️🤔 Frequently asked questions
What happens if I don't set up a redirect from index.php at all?
The search engine will choose a canonical version on its own, but not necessarily the one you need. Part of the link equity will go to the duplicate, and both URLs may alternate in search results. There's no direct threat of penalties, but rankings will be lower than they could be with a clean structure. John Mueller from Google has repeatedly emphasized that canonicalization via
rel="canonical"is a hint to the search engine, not a directive. Google may ignore the canonical and choose a different page if it considers it more relevant. A 301 redirect is a directive: it guarantees weight transfer and excludes the duplicate from the index.
Can I use Redirect 301 /index.php / instead of mod_rewrite?
Technically yes, but for index files this is dangerous. After redirecting to
/, Apache again substitutesindex.phpviaDirectoryIndex, theRedirectrule triggers again, resulting in an infinite loop, and the browser cuts it off with anERR_TOO_MANY_REDIRECTSerror.RewriteCondwith the%{THE_REQUEST}check doesn't have this problem: it analyzes the original request from the browser, not the one rewritten by the server's internal rules.
Do I need to set up a redirect if the site only works over HTTPS?
Yes. HTTPS and index duplicates are two independent issues. Even with an HTTP→HTTPS redirect set up and correct
rel="canonical", a direct request tohttps://site.ru/index.phpwill return a 200 code without a redirect. The rules from method 1 cover both protocols:RewriteRuleexplicitly specifieshttps://in the target URL.
How do I verify the redirect hasn't broken the site?
Three checkpoints: 1) the homepage opens at root
/without redirects (curl -Ishould return 200); 2) URLs withindex.phpandindex.htmlreturn 301 and lead to/; 3) the WordPress admin (/wp-admin/) works without loops. The last point is critical: a poorly written rule in.htaccesscan intercept requests toindex.phpinside the admin and break login. The construct from method 1 is safe: it checks for an exact URI match and doesn't touch/wp-admin/index.php.
What about other index files like index.aspx or index.py?
The mechanics are the same: copy the
RewriteCond+RewriteRuleblock, replace the extension, and add it to.htaccess. For non-standard extensions, make sure the file physically exists in the root and is listed inDirectoryIndex; otherwise the server won't be able to serve it as an index file anyway, and no redirect will be needed.
Dealing with index file duplicates: final checklist
Setting up a 301 redirect from index.html and index.php to the root is a "five minutes of work, years of protection" task. The rule lives in .htaccess or index.php transparently and requires no maintenance when you change designs or move to a different hosting.
Steps to take after making the changes:
- Verify the redirect via
curl -Iorredirectchecker.com; the response should be 301. - Make sure the homepage opens at root with a 200 code.
- Search for
href="/index.php"andhref="/index.html"in the page source code; replace each occurrence withhref="/". - In Google Search Console, run an inspection of the homepage; the bot should see a 200 and the canonical URL without
/index.php.
After this, duplicates will gradually disappear from the "Coverage" report in Search Console, and backlink equity will concentrate on a single canonical page. The result isn't instant (the search engine needs time to recrawl), but it's inevitable.



