Skip to content

WordPress Downloading a File Instead of Opening in Browser? 8 Fixes (2026)

WordPress downloading a file instead of opening means the server stopped running PHP. Confirm from the Content-Type header, then fix the handler or .htaccess.

Sunny Kumar
Sunny Kumar11 min read
TL;DR

When WordPress downloads a file instead of loading your site, the server has stopped running .php as code and is handing it over as a raw download. Nine times out of ten it is a stale PHP handler in .htaccess after a PHP upgrade, or a corrupted .htaccess file. Confirm it from the file's Content-Type, then reset .htaccess and set the right PHP version in cPanel.

I have walked into this one on client sites more than once. You type in the URL, expecting the homepage, and instead the browser quietly downloads a file called download or index.php. No error, no white screen. Just a file sitting in your downloads folder.

It looks scary, but it is almost never your content. Your posts and database are fine. What broke is one layer underneath.

The server stopped running PHP as code. That is the whole problem, and it is usually a five-minute fix.

So the first time it happened to me, I did the slow thing and reinstalled half the site. The second time I learned the shortcut. This guide is that shortcut, in the order I actually work through it.

Why does WordPress download a file instead of opening?

A WordPress page is a .php file. When a visitor hits it, the server is supposed to hand that file to the PHP interpreter, run it, and send back finished HTML. The browser sees Content-Type: text/html and draws the page.

When that handoff breaks, the server gives up and serves the raw .php file as a generic binary, usually with Content-Type: application/octet-stream. Your browser does not know what to do with a binary, so it does the safe thing and downloads it.

So the real question is never "why is my site broken." It is "why did the server stop running PHP." And there are only a handful of reasons.

The two that account for nearly every case I see:

  • A stale PHP handler in .htaccess. Your host upgraded PHP, but your .htaccess still points .php at a version that no longer exists on the server. Apache shrugs and serves the file.
  • A corrupted .htaccess file. A plugin, a bad edit, or injected malware mangled the rules.

The rest, cache plugins, file permissions, a CDN setting, are real but rarer.

Start with the common two and you are done in five minutes, nine times out of ten.

First, confirm the diagnosis (30 seconds)

Before you touch a single file, prove what is happening.

Confirm the cause from one header before you change anything, or you will fix the wrong thing.

Open the page in Chrome, hit F12, go to the Network tab, and reload. Click the first request and look at the Response Headers.

  • Content-Type: text/html means PHP is running and your problem is something else (a redirect, a download link, a plugin).
  • Content-Type: application/octet-stream (or application/x-httpd-php) confirms it: the server is sending raw PHP, not running it.

No DevTools handy? Just open the file it downloaded in a text editor. If you can read your theme's PHP code in plain text, the server never executed it. That is your confirmation.

Now you know it is a handler problem, not a content problem. Here is the order I work through.

The 8 fixes at a glance

#FixDifficultyBest when
1Set the right PHP versionEasyAfter a host PHP upgrade
2Reset .htaccessEasyThe single most common fix
3Remove stale AddHandler linesEasyOld handler lines linger
4Disable your cache pluginEasyStarted after a cache update
5Check file permissionsMediumAfter a migration or bad chmod
6Scan for malwareMedium.htaccess keeps coming back
7Check Cloudflare / CDNMediumOnly some pages, behind a CDN
8Turn on the debug logMediumNothing above worked
Warning

Back up before you edit

Three of these fixes touch .htaccess or wp-config.php, and one bad character in either can take the whole site offline. Download a copy of the file before you change it, so you can put it back in seconds. If you can still reach the dashboard, run a full backup first.

Method 1

Set the right PHP version

Best for: Sites that broke right after the host upgraded PHP. This is the root cause behind most stale handlers.

This is where I start, because it is usually the actual cause. When a host moves you from, say, PHP 7.4 to 8.2, any handler pointing at the old version breaks, since that version is gone.

In cPanel, open MultiPHP Manager. You will see each domain and the PHP version it currently uses.

cPanel and WHM documentation page for MultiPHP Manager, showing the interface used to set the PHP version for each domain on a server
cPanel's MultiPHP Manager is where you set the PHP version per domain. After a host upgrades PHP, this is the first place I look.
  1. Tick the affected domain.
  2. From the PHP Version dropdown, pick a current, supported release. PHP 8.1 or newer is the safe choice today.
  3. Click Apply.

Setting the version cleanly often regenerates the correct handler and the download stops on the spot. It is worth knowing that around a quarter of WordPress sites still run PHP older than 8.0, with PHP 7.4 alone sitting near 18 percent, so a lot of sites are one host upgrade away from exactly this problem.

No cPanel? On a managed host (Kinsta, WP Engine, SiteGround) the PHP version lives in the dashboard, or you ask support to set it.

Method 2

Reset your .htaccess file

Best for: Almost everyone. If one fix solves this for the most people, it is this one.

.htaccess is the rules file Apache reads on every request. If it is corrupted or carries an old handler line, the server serves your pages as downloads.

Resetting it to the WordPress default is the single fix that clears this for the most people.

Connect with FTP or your host's File Manager and open .htaccess in your site root (the folder with wp-config.php). Turn on "show hidden files" if you do not see it.

  1. Download a copy first. This is your undo button.
  2. Open the file and delete everything inside.
  3. Paste in the current default block, from the official WordPress server docs:
apache
# BEGIN WordPress

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]

# END WordPress
  1. Save, then reload your site in a private window.

If the site loads, the old .htaccess was the culprit. You can rebuild a clean copy any time by going to Settings → Permalinks in the dashboard and clicking Save once, which WordPress uses to regenerate this file.

Tip

Check every folder, not just the root

A subdirectory install, or a /wp-admin/ of its own, can carry its own .htaccess. If the root reset does not fix it, look for a second .htaccess deeper in the tree with a bad handler line. The same trick that powers a clean .htaccess redirect can also break a site when the syntax is wrong.

Method 3

Remove stale AddHandler lines

Best for: Sites where a plugin or old tutorial left a hard-coded PHP handler in .htaccess.

Sometimes the reset is not enough because a plugin keeps writing the bad line back, or it lives outside the WordPress block. Open .htaccess again and hunt for any line that names a PHP version directly:

apache
# These are the troublemakers, delete or comment them out:
AddHandler application/x-httpd-php74 .php
AddHandler application/x-httpd-php5 .php
AddType application/x-httpd-php .php

Any handler that names a PHP version your server no longer runs will break execution. Delete those lines, or put a # in front of each to comment it out, then save.

On a modern cPanel server you do not need a manual handler at all, the panel generates the correct one. So in most cases the right move is to remove the line, not rewrite it. If it keeps reappearing after a reset, a plugin is writing it, which points you straight to the next fix.

Method 4

Disable your cache plugin

Best for: Sites that broke right after a caching plugin update or a cache flush.

Caching plugins write their own rules into .htaccess. WP Super Cache, W3 Total Cache, WP Fastest Cache and WP Rocket all do this, and if their rules reference a handler that has moved, the page comes down as a file.

If you can still reach the dashboard, deactivate the cache plugin, clear the cache, and reload.

Locked out of wp-admin too? Disable it over FTP instead. Rename the plugin's folder inside wp-content/plugins/:

bash
# Rename to switch it off without deleting it
wp-content/plugins/w3-total-cache  →  wp-content/plugins/w3-total-cache.off

WordPress cannot find the plugin under the new name, so it deactivates it safely. Reload the site. If it comes back, that plugin was the cause, reset .htaccess once more (Fix 2) to clear any rules it left behind, then reinstall a fresh copy.

Method 5

Check file permissions

Best for: Sites that broke after a migration, a restore, or a manual chmod.

Wrong permissions can stop PHP files from being read and executed, which shows up as the same download behaviour. This one comes up most after a migration or a clumsy bulk chmod.

The values WordPress recommends, per its hardening guide:

TargetPermission
Directories755
Files644
wp-config.php400 or 440

Over SSH you can set them in two commands from your site root:

bash
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;

Then lock down the config file on its own:

bash
chmod 440 wp-config.php

One firm rule: never set anything to 777. It means anyone can write to the file, and it is one of the first things attackers look for. If a tutorial tells you to chmod 777, close the tutorial.

Method 6

Scan for malware

Best for: Sites where .htaccess keeps getting corrupted no matter how often you reset it.

If you reset .htaccess, it works for an hour, then the download is back, you are not chasing a config bug.

Something is rewriting the file, and that is almost always injected code.

This is not a rare edge case. Patchstack recorded 11,334 new WordPress vulnerabilities in 2025, up about 42 percent on the year before, and almost all of them sit in plugins and themes, not core.

Wordfence homepage describing its free, premium, care and response plans for WordPress security and malware scanning
Wordfence is the scanner I install first when a file keeps getting rewritten. The free version flags injected code in .htaccess and core files.

Two checks I run:

  1. Install Wordfence and run a full scan. Its free tier flags modified core files and suspicious code in .htaccess.
  2. Verify core files over WP-CLI if you have SSH:
bash
wp core verify-checksums

This downloads the official checksums for your version and compares them to your files. Any line it flags is a core file that has been changed, a strong sign of a hack.

If core is compromised, reinstall it cleanly from Dashboard → Updates → Reinstall, which overwrites core files without touching your content. A solid security plugin is one of the must-have WordPress plugins for exactly this reason.

Method 7

Check Cloudflare and CDN settings

Best for: Sites behind a CDN where only some pages download, or the problem clears in a private window.

If you run Cloudflare or another CDN, the edge sits between the visitor and your server, so a setting there can change what the browser receives even when your origin is fine. The tell: it happens on some pages, or it disappears when you bypass the cache.

Cloudflare CDN product page describing its global, enterprise-grade content delivery network
Cloudflare sits in front of your site, so a wrong setting here changes what the browser gets. Automatic Signed Exchanges is the one I disable first.

The usual offender is Automatic Signed Exchanges (SXG). Site owners have reported on Cloudflare's own community forum that it can break rendering in Chrome. To rule it out:

  1. In your Cloudflare dashboard, go to Speed → Optimization (or Caching) and turn Automatic Signed Exchanges off.
  2. Go to Caching → Configuration and click Purge Everything.
  3. Reload your site in a private window.

While you are there, check Page Rules and Transform Rules for anything that rewrites response headers or content type. Test with the CDN paused (Overview → Pause Cloudflare on Site) to confirm whether the edge or the origin is at fault.

Method 8

Turn on the debug log

Best for: When nothing above worked and you need the server to tell you what is actually failing.

If you are still here, stop guessing and make WordPress show its work. Edit wp-config.php and, just above the /* That's all, stop editing! */ line, add:

php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Reload the site, then read wp-content/debug.log. A fatal error naming a plugin or a missing PHP function tells you exactly where to look, far faster than trying fixes blind.

Turn debugging back off once you are done. Leaving WP_DEBUG on in production can leak paths and warnings to visitors.

How to stop it happening again

Most of the time this traces back to a PHP upgrade nobody planned for. A few habits keep it from biting twice:

  • Back up .htaccess before any plugin or server change. It is the file that breaks, and a copy makes recovery instant.
  • Watch for PHP upgrade notices from your host. When they bump the version, check the site loads the same day.
  • Test changes on staging first. Most decent hosts give you a one-click staging copy. Break things there, not in production.
  • Keep one trusted security plugin running. It catches the malware route before it corrupts anything.

If your site is slow to recover from these every time, that is usually an infrastructure problem worth fixing properly. Treat it as a technical SEO and hosting job, not a recurring fire drill.

When to call your host

Some of this lives on the server, not in your dashboard. If you have reset .htaccess, set a current PHP version, ruled out plugins and malware, and the debug log points at the server, it is time to open a ticket.

The phrase that gets a useful answer: tell them your .php files are being served as downloads instead of executing, and ask them to check the PHP handler and, on Nginx, the PHP-FPM socket. That tells a competent support engineer exactly where to look, instead of sending you the generic "clear your cache" reply.

Final take

A site that downloads instead of opening looks like a disaster and is usually a five-minute fix.

The content is safe. The server just stopped running PHP.

So confirm it from the Content-Type first, then work the common two: set a current PHP version, and reset .htaccess. That clears it for most sites. If .htaccess keeps getting rewritten, scan for malware. If only some pages break, look at your CDN. And if all of that comes up clean, the debug log and your host will close it out.

Site doing something strange and you would rather not guess?

We fix the WordPress problems that do not show a clean error, broken handlers, corrupted configs, hacked core files, on shared hosting and managed alike. Send us the symptom and the first reply comes from Sunny, not a ticket queue.

See WordPress development

Common questions

Why does WordPress download a file instead of opening the page?

Because the server stopped running your .php files as code. When PHP is not wired up, after a PHP upgrade, a broken handler, or a corrupted .htaccess, the server sends the raw file with a Content-Type like application/octet-stream, and the browser downloads it instead of showing the page.

How do I fix index.php downloading instead of loading?

Reset .htaccess to the WordPress default and set the correct PHP version in your host panel. In cPanel, open MultiPHP Manager, pick a current PHP 8.x version for the domain, then replace .htaccess with the default block. That fixes the large majority of cases on shared hosting.

What is the default WordPress .htaccess code?

It is a short mod_rewrite block between # BEGIN WordPress and # END WordPress that routes every request through index.php. You can copy the current version from the official WordPress server documentation, paste it in, and save. Back up the old file first.

Can a caching plugin cause WordPress to download files?

Yes. Cache plugins like WP Super Cache, W3 Total Cache and WP Rocket write their own rules into .htaccess, and if those rules reference a PHP handler that no longer exists, the server serves the page as a download. Disable the plugin and reset .htaccess to test.

How do I check what PHP version my site uses?

In cPanel open MultiPHP Manager, where each domain shows its current PHP version. Without cPanel, add a file with <?php phpinfo(); ?>, load it once, then delete it, or check Tools, Site Health, Info in the WordPress dashboard if the site still loads.

What if none of the fixes work?

Turn on the debug log to read the real error, then contact your host. If PHP-FPM is down or the server MIME mapping is wrong, only the host can fix it. Give them the exact symptom, that .php is served as a download instead of executing, so they check the handler.

Written by
Sunny Kumar
Sunny KumarSEO Specialist & product builder

SEO Specialist and product builder with 10+ years in search. The notes come from the work, not the theory.

Work with TheGuideX

Reading about it is the easy part.

Send us the site and the problem. Your first reply comes from Sunny Kumar — not a sales team — and tells you if it is a fit.