Your post lives at example.com/index.php/about-us/ and it looks broken. It isn’t broken.

That prefix means the web server never learned to rewrite clean paths to the front controller, so WordPress fell back to PATHINFO permalinks.

Knowing how to remove index.php from WordPress URLs takes about ten minutes once you identify the server.

Here’s what this covers:

  • Why the prefix appears on Apache, Nginx, LiteSpeed, and IIS
  • The exact rewrite rules, from .htaccess to tryfiles
  • 301 redirects so both URL versions stop resolving
  • Fixes for the 404s and 500 errors that follow

Managed hosts get their own section, since Kinsta and WP Engine ignore .htaccess entirely.

What Is index.php in a WordPress URL?

index.php is the front controller file sitting in the WordPress root directory. Every request that hits the site loads it, because index.php calls wp-blog-header.php, which boots the whole CMS.

The file staying on disk is mandatory. The file showing up inside the address bar is not.

Two URL formats exist side by side in WordPress:

  • Pretty permalinks: example.com/about-us/ (server-level URL rewriting active)
  • PATHINFO permalinks: example.com/index.php/about-us/ (no rewriting, path passed through the front controller)

W3Techs data from 2026 puts WordPress at 41.9% of all websites and roughly 59% of sites running a known CMS, so the PATHINFO format shows up on a lot of installs.

Removing index.php touches rewrite configuration only. Deleting the actual file kills the site instantly.

Why Does index.php Appear in WordPress URLs?

index.php appears when the web server cannot rewrite clean paths to the front controller. WordPress detects the missing rewrite support during permalink setup and falls back to the PATHINFO structure automatically, prefixing every post and page URL with /index.php/.

5 root causes produce this behavior: modrewrite disabled on Apache, AllowOverride None in the virtual host, a permalink structure manually saved with the prefix, Nginx running without a tryfiles directive, and a missing URL Rewrite Module on IIS.

CauseServerWhat you see
mod_rewrite not loadedApacheindex.php prefix appears on every post URL
AllowOverride NoneApache.htaccess file is created but ignored
Missing try_files directiveNginx404 errors on clean URLs
URL Rewrite Module missingIIS500 errors or index.php prefix in URLs

Server share explains why this keeps happening. W3Techs (January 2026) puts Nginx at 33.3%, Cloudflare Server at 25.8%, and Apache at 24.4% of sites with a known web server.

Nginx has no .htaccess equivalent. Any WordPress tutorial telling you to paste a rewrite block into a file will do nothing on a third of the web.

The Netcraft November 2025 survey recorded Nginx gaining 6.4 million sites in a single month while Apache lost 3.6 million, its largest drop in the survey’s history. That migration is the reason permalinks stop working after a host change so often.

How to Check Which Server Software Runs the Site

Check the server before touching any config file. The correct fix depends entirely on whether Apache, Nginx, LiteSpeed, or IIS answers the request, and applying an Apache rewrite block to an Nginx stack wastes an afternoon.

4 reliable checks:

  • WP admin: Tools > Site Health > Info > Server reads $SERVER['SERVERSOFTWARE'] for you
  • Command line: curl -I https://example.com and read the Server: response header
  • phpinfo(): shows loaded Apache modules, the SAPI in use, and where the php.ini file sits on disk
  • Hosting panel: cPanel, Plesk, and Cloudways all name the stack in the server info screen

One caveat on the Server: header. Cloudflare rewrites it, so a site behind the proxy reports cloudflare and hides the origin.

LiteSpeed and OpenLiteSpeed read Apache syntax. They hold roughly 14.8% of the market (W3Techs, March 2026), and .htaccess rules work on them without modification.

How to Remove index.php From WordPress URLs

Removing index.php requires 1 of 5 methods, ranked from lowest to highest technical risk: re-saving the permalink structure, editing .htaccess on Apache, adding a tryfiles directive on Nginx, adding a rewrite rule to web.config on IIS, or falling back to a redirect plugin.

Resetting the Permalink Structure in WordPress Settings

Start here. It fixes the problem outright on maybe half of affected sites.

  • Open Settings > Permalinks
  • Select Post name
  • Click Save Changes, then click it a second time

Saving flushes the stored rewrite rules from the wpoptions table and regenerates the .htaccess block. The regeneration only fires when the root directory is writable, so correcting file permissions to 644 on .htaccess and 755 on the root folder comes first.

Removing index.php With .htaccess on Apache

The default WordPress block:

<IfModule modrewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index.php$ - [L] RewriteCond %{REQUESTFILENAME} !-f RewriteCond %{REQUESTFILENAME} !-d RewriteRule . /index.php [L] </IfModule> `

The two RewriteCond lines check whether the request matches a real file or directory. Everything else routes to index.php silently.

Placement matters. The block belongs between the # BEGIN WordPress and # END WordPress markers, and anything outside those markers survives a permalink re-save.

When AllowOverride Blocks the Rewrite Block

Apache ignores .htaccess entirely under AllowOverride None. Set it to AllowOverride All in the vhost or apache2.conf, then run a2enmod rewrite and reload.

Removing index.php on Nginx With tryfiles

Nginx never reads .htaccess. Not on startup, not per request, never.

The equivalent lives in the server block:

` location / { tryfiles $uri $uri/ /index.php?$args; } `

Validate with nginx -t before reloading with systemctl reload nginx. A syntax error in a reload takes the whole server down, not just one site.

Removing index.php on IIS With web.config

Prerequisite: the URL Rewrite Module from Microsoft, installed through Web Platform Installer or the standalone MSI.

Rule: a section inside matching . with conditions on IsFile and IsDirectory set to negative, rewriting to index.php.

After the edit: recycle the application pool. IIS caches config in memory and stale rules produce confusing 404 results.

Using a Plugin When Server Access Is Restricted

Plugins do not restore rewrite support. They intercept the request in PHP and issue a redirect after WordPress has already loaded, which costs a full bootstrap on every hit.

Three options handle it: Redirection (2 million-plus active installs, maintained by John Godley of Automattic), Permalink Manager Lite for structure-level control, and Yoast SEO Premium, whose redirect manager sits behind the paid tier despite the free plugin passing 13 million installs.

Honest limitation: a PHP-level redirect masks the symptom. Server-level rules resolve the request before PHP starts.

Which Permalink Structures Work Without index.php?

All 5 built-in permalink structures work without index.php once modrewrite or tryfiles is active. Post name, Day and name, Month and name, Numeric, and Custom Structure produce clean URLs. Plain never uses index.php because it relies on query strings instead.

StructureResultPrefix risk
Post name/sample-post/None when rewriting is enabled
Day and name/2026/07/24/sample-post/None when rewriting is enabled
Numeric/archives/123/None when rewriting is enabled
Plain/?p=123Never affected

Backlinko’s analysis of 11.8 million search results found the average first-page URL runs 66 characters, with position-one results averaging 9.2 characters shorter than position ten. Stripping /index.php removes 10 characters from every URL on the site.

Check the Custom Structure field directly. WordPress writes /index.php/%postname%/ there when it detects no rewrite support, and deleting the prefix by hand only holds if the server can actually rewrite.

Pagination inherits the same rules, so /page/2/ and attachment URLs clean up in the same pass. The category base behaves independently, which matters if you also plan on stripping the category slug from post URLs.

How to Redirect Existing index.php URLs to Clean URLs

Add a 301 redirect after the rewrite fix. Without one, both /index.php/sample-post/ and /sample-post/ return HTTP 200, giving Google two indexable addresses for identical content and splitting internal PageRank between them.

Apache:

` RewriteCond %{THEREQUEST} ^[A-Z]{3,9} /index.php/ RewriteRule ^index.php/(.)$ /$1 [R=301,L] `

Nginx: rewrite ^/index.php/(.*)$ /$1 permanent;

Google Search Central states plainly that duplicate URLs waste crawling time on a site, and calls perceived inventory the factor site owners control most.

Test both versions with curl -I. One returns 301, the other returns 200. If both return 200, the redirect never fired.

Then clean the database. WP-CLI handles it safely with wp search-replace ‘example.com/index.php/’ ‘example.com/’ –precise –recount, or Better Search Replace does the same through the admin, which also repairs the internal links pointing between your posts.

One exception worth keeping. Leave /index.php itself reachable, since the REST API and wp-cron.php route through it.

How to Remove index.php From Multisite and Subdirectory Installs

Multisite and subdirectory installs need a different rewrite block. The standard WordPress rules assume core files sit in the document root, so subdirectory multisite, subdomain multisite, and Composer-based installs each require their own RewriteBase value and rule set.

Install typeRewriteBaseExtra rule
Single site, root/None
Single site, /blog//blog/None
Subdirectory multisite/Site-scoped wp-admin and file handling rules
Subdomain multisite/RewriteRule ^ - [L]

Subdirectory multisite (WordPress 3.5 and later) rewrites /site2/wp-admin/ and /site2/files/ before the catch-all rule, and dropping either one breaks the network dashboard.

Subdomain multisite uses a shorter block, with RewriteRule ^ – [L] sitting directly under the wp-admin rule to stop further processing.

Composer-based setups deserve their own note. Bedrock from Roots serves from a web/ directory with core in web/wp/, so WPHOME and WPSITEURL in wp-config.php must point to different values, otherwise clean URLs resolve to the wrong path.

Mismatched RewriteBase is the usual culprit on subdirectory installs. Set it to the install folder, not the root, and re-save permalinks afterward.

How to Remove index.php on Managed WordPress Hosts

Managed WordPress hosts control rewrite rules at the platform level. WP Engine, Flywheel, and Pantheon ignore .htaccess completely, so index.php removal happens through a control panel rule or a support request instead of a file edit you make yourself.

MalCare’s host breakdown splits the market cleanly: GoDaddy, SiteGround, Bluehost, Nexcess, Liquid Web, Cloudways, and DreamHost read .htaccess. WP Engine, Flywheel, and Pantheon do not.

Host.htaccessWhere rewrite rules live
WP EngineDeprecatedWeb Rules Engine in the User Portal
KinstaAbsentMyKinsta redirects or a support ticket
PantheonIgnoredPHP snippet included in wp-config.php
CloudwaysAvailablepublic_html after switching web root

WP Engine announced the end of .htaccess support and replaced it with the Web Rules Engine, which handles access rules, headers, and rewrites from the portal. Their own documentation notes that default WordPress rewrites already run at the server level, so most sites there never see the prefix.

Kinsta: runs Nginx, so no .htaccess file exists on the account. The support team adds custom rules to the Nginx config, though their docs state they will not convert Apache syntax for you.

Pantheon: runs one tuned nginx.conf across every container and does not accept per-site modifications. The Pantheon htaccess Rewrites repository ports Apache rules into PHP, loaded at the very top of wp-config.php before WordPress boots.

Cloudways: layers Apache behind Nginx. Switch the Webroot Path to publichtml under Application Settings, then create .htaccess there.

SiteGround runs the same hybrid and honors .htaccess through Site Tools without extra steps.

Enterprise platforms sit further along the same spectrum, where the WordPress VIP model of managed infrastructure puts every rewrite decision in the platform team’s hands.

What Errors Appear After Removing index.php and How to Fix Them

6 failures follow index.php removal: 404 on every post except the homepage, a 500 internal server error, an admin redirect loop, an infinite redirect from a self-referencing rule, broken image paths after a database replace, and clean URLs reverting on the next permalink save.

SymptomCauseFix
404 on all postsRewrite rules are not flushedRe-save Permalinks settings
500 errorMalformed .htaccess directiveRename the file, then reload the site
Redirect loopRule matches its own destination URLAdd a THE_REQUEST condition
Missing imagesSerialized data is corruptedRestore the data, then replay the migration with --precise

404 on every post: the homepage answers because it does not depend on rewriting. Everything else fails until the rules cached in wpoptions get regenerated, which is the standard cause behind WordPress 404 errors after any permalink change.

500 internal server error: a single invalid directive takes down the entire site, and multiple sources name a corrupt .htaccess as the most frequent trigger of the 500 internal server error. SiteLock data puts plugin conflicts at 28% of 500 errors, permission problems at 20%, and database corruption at 14%.

Admin redirect loop: siteurl and home hold different values in the options table. Set both to the same clean URL and the loop stops.

Infinite redirect: the 301 rule catches its own output. Match against %{THEREQUEST} instead of the rewritten path so the rule fires once per original request.

Broken images: a search-replace run without –precise corrupts serialized arrays in postmeta, which leaves images failing to display across the media library. Restore the backup and replay the command properly.

Recovery, in order:

  • Rename .htaccess to .htaccessold over FTP
  • Load the site to confirm the file was the problem
  • Log in, open Settings > Permalinks, click Save

That sequence takes about two minutes and resolves more cases than anything else on the list.

How to Verify index.php Removal Is Working

Verification requires 4 checks at server level: a curl request against the old URL, a full-site crawl filtered for the prefix, URL Inspection in Google Search Console on both versions, and wp rewrite list to read the active rules from the database.

Command line:

` curl -I https://example.com/index.php/sample-post/ `

A working setup returns 301 plus a Location: header pointing at the clean URL. A 200 response means the redirect never fired.

CheckToolPass condition
Redirect statuscurl -IReturns 301 redirect to the clean URL
Site-wide scanScreaming FrogZero URLs contain index.php
Active ruleswp rewrite listNo PATH_INFO patterns are present
Index statusSearch ConsoleClean URL is marked as canonical

Screaming Frog’s free build crawls 500 URLs per session, enough for most blogs, with the licence at £199 per year for anything larger. Filter the Internal tab by index.php and the count should read zero.

Google Search Console’s URL Inspection tool answers the question that matters commercially. Run both versions and check which one Google reports as the user-declared and Google-selected canonical.

Page source counts too. The rel=”canonical” tag on every post should carry the clean URL, and Yoast SEO writes that tag automatically once the permalink structure is correct.

When something still misfires, reading the WordPress error log beats guessing at the config file.

How Does Removing index.php Affect Crawling and Rankings?

Removing index.php produces no direct ranking boost on its own. The gain comes from consolidation: Google treats /index.php/post/ and /post/ as two separate URLs, splitting internal PageRank between them and spending crawl requests on duplicates of pages it already has.

Google Search Central names perceived inventory as the crawl factor site owners control most, and states directly that duplicate URLs waste a lot of crawling time on a site.

3 real effects, ranked by size:

  • PageRank consolidation: one URL receives the internal links instead of two competing paths
  • Crawl efficiency: larger catalogs and archive pages stop burning requests on mirrored addresses
  • Click-through: readable URLs read better in the SERP, and Backlinko found position-one results average 9.2 characters shorter than position ten

Perspective helps here. Google’s own guidance limits crawl budget concerns to bigger sites, so a 40-post blog gains almost nothing beyond tidier addresses.

The WordPress developer handbook states the behavior plainly: without server modifications on Nginx, index.php gets added to your permalinks. That is a configuration outcome, not a penalty.

When to leave index.php alone:

  • The site has ranked on those URLs for years
  • Canonical tags already point to a single version
  • Search Console shows no duplicate URL coverage issues

Changing every URL on an established site carries migration risk. A botched redirect map costs more traffic than the prefix ever did, and Redirection’s 404 log (2 million-plus installs) exists precisely because those migrations go sideways.

Fix it on new builds. Weigh it carefully on old ones.

FAQ on How To Remove Index.Php From WordPress URLs

Can I just delete the index.php file?

No. Deleting index.php takes the entire site offline, because that file loads wp-blog-header.php and boots WordPress on every request. Removal applies to the URL string only, through rewrite rules at server level.

Why did index.php come back after I changed hosts?

The new host runs Nginx. WordPress writes .htaccess on permalink save, Nginx ignores it, and the fallback structure returns automatically. Add a tryfiles directive to the server block and the prefix disappears again.

Do I need a plugin to remove index.php?

Not on Apache, LiteSpeed, or IIS. Plugins like Permalink Manager Lite and Redirection intercept requests in PHP after WordPress loads, which costs a full bootstrap per hit. Server-level rewrite rules resolve the request first.

Will removing index.php hurt my rankings?

Only if the 301 redirects are missing. Without them, both URL versions return 200 and split internal PageRank. With correct redirects and canonical tags in place, consolidation helps slightly and rankings hold steady.

Where exactly does the rewrite block go in .htaccess?

Between the # BEGIN WordPress and # END WordPress markers in the root directory file. Anything you place outside those markers survives a permalink re-save, since WordPress only rewrites what sits between them.

Why do all my posts return 404 after the change?

The stored rewrite rules never flushed. Open Settings > Permalinks and click Save Changes twice, or run wp rewrite flush. The homepage keeps loading because it does not depend on URL rewriting.

How do I fix internal links pointing at the old URLs?

Run WP-CLI search-replace with the –precise flag, or use Better Search Replace from the admin. Skipping the flag corrupts serialized postmeta, which is a common source of broken links across a WordPress site.

Does the fix work the same on multisite?

No. Subdirectory multisite needs extra rules for /site2/wp-admin/ and /site2/files/ before the catch-all. Subdomain networks use a shorter block with RewriteRule ^ – [L] stopping further processing.

What if my host blocks .htaccess edits?

WP Engine, Flywheel, and Pantheon ignore the file entirely. Use the Web Rules Engine on WP Engine, MyKinsta redirects on Kinsta, or a PHP snippet loaded at the top of wp-config.php on Pantheon.

How do I confirm the removal actually worked?

Run curl -I against the old URL and look for a 301 with a Location: header. Then crawl the site in Screaming Frog and filter for index.php. Zero results means done.

Conclusion

Knowing how to remove index.php from WordPress URLs comes down to one question: which server answers the request. Everything after that is syntax.

Check Site Health first. Then apply the matching fix: modrewrite with AllowOverride All on Apache, a tryfiles directive on Nginx, the URL Rewrite Module on IIS.

The finishing steps decide whether it holds:

  • Save permalinks twice to flush the rewrite rules
  • Add the 301 so duplicate URLs stop resolving
  • Verify with wp rewrite list` and a curl request
  • Watch canonical selection in Search Console for a few weeks

One habit worth keeping: re-check the prefix after every migration or host change.

RewriteBase values and Nginx server blocks do not travel with the database, and the fallback structure comes back quietly.