If a speed test told you to remove query strings from static resources, here is the answer as of September 2026: do not. The advice dates from 2008, the tools that made it famous have since withdrawn it, and stripping the ?ver= that WordPress appends to your CSS and JavaScript removes the mechanism that makes sure visitors get new files after an update.
This guide explains what the query string is doing there, where the recommendation came from and when it died, what actually goes wrong when you remove it, and, for the cases where you still want to, the three ways to do it with the risk stated plainly. If you came here from a hosting dashboard or an older speed tool that still flags it, the short section on which tools still show the warning should save you the trouble.
- The “remove query strings from static resources” recommendation is retired. Google dropped it in 2014, GTmetrix marks it deprecated, and Lighthouse has no such audit.
- WordPress adds
?ver=on purpose. It is cache-busting: when a plugin, theme or core updates, the new version string makes browsers and CDNs fetch the new file. - Stripping it can leave visitors on stale CSS and JavaScript after updates. Perfmatters removed its own option for exactly this reason, and WP Rocket removed theirs in version 3.6.
- It moves no modern speed score. WP Rocket measured identical results with and without query strings before removing the setting.
- If you must, W3 Total Cache still has the checkbox, a small plugin does it, and the PHP snippet below does it. All three carry the same risk.
What the query string is doing there
Look at the source of any WordPress page and you will see lines like this:
<link rel="stylesheet" href="https://example.com/wp-content/plugins/some-plugin/style.css?ver=4.2.1">
<script src="https://example.com/wp-includes/js/jquery/jquery.min.js?ver=3.7.1"></script>
The ?ver= part is added by WordPress itself. When a plugin or theme enqueues a file with wp_enqueue_style() or wp_enqueue_script() it passes a version number, and WordPress appends it to the URL. When no version is passed, core appends its own version instead (that is what default_version in wp-includes/script-loader.php does), which is why plain core files carry the WordPress version.
That number is a cache buster. Browsers and CDNs are told to keep static files for a long time, often a year, precisely so they do not re-download them on every page view. The version string is how a cached file gets replaced: style.css?ver=4.2.1 and style.css?ver=4.3.0 are different URLs, so the moment a plugin updates, every visitor fetches the new stylesheet without anyone clearing anything. Remove the query string and both versions are simply style.css, and a browser that cached it last month has no reason to ask again.
This is not a WordPress quirk. It is what current guidance recommends. Lighthouse’s “Serve static assets with an efficient cache policy” audit tells you to set Cache-Control: max-age=31536000 (one year) and to put a version or hash in the file URL so that each release is unique and “prompting the browser to fetch the new version.” WordPress’s query string is the built-in way of doing exactly that.
Where the advice came from, and when it died
The recommendation was real once. Around 2008, the Squid proxy cache, then very widely deployed, refused to cache any URL containing a question mark, even when the response said it was cacheable. Google’s original PageSpeed rules told developers to keep query strings off static files so those proxies would cache them. Everything since then has been the slow death of that rule:
| When | What changed |
|---|---|
| May 2008 | Squid 2.7 ships and caches URLs with query strings by default. The original problem is fixed. |
| December 2014 | Google removes the rule from PageSpeed Insights. |
| 2020 | GTmetrix rebuilds its report on Lighthouse and marks its Remove query strings from static resources page “deprecated”; it no longer counts toward grades. |
| 2020 | WP Rocket, which had added a “Remove query strings” option in version 2.9, removes it in version 3.6 after measuring identical speed results with and without query strings. |
| Since | Perfmatters removes its option in version 1.6.6 and says it no longer recommends the practice. PageSpeed Insights, Lighthouse and WebPageTest show no warning for it. |
WP Rocket’s reasoning for removing the option is the whole argument in one sentence: “Modern browsers and proxies cache based on headers and not based on the presence of query strings.” Caching decisions are made from Cache-Control, ETag and Last-Modified headers. Whether the URL has a question mark in it has not mattered to any mainstream cache for well over a decade.
You will still find plenty of articles, some from CDN companies and dated 2018, insisting that removing query strings is “important”. They were written for the previous era and never updated. This post was one of them until this revision, which is why it now leads with the correction.
What actually goes wrong when you remove them
Nothing, on the day you do it. The problems arrive with the next update.
- A plugin or theme updates its CSS or JavaScript. The file name is unchanged, so browsers that cached the old file keep using it until their cache expires. With the one-year lifetime that every caching guide recommends, that can be a very long time. Layout breaks and script errors appear for returning visitors and not for you, because you are logged in and testing with a fresh cache.
- Page builders suffer most. Perfmatters notes that removing query strings “causes problems with popular page builder plugins like Elementor and Beaver Builder,” and with the WordPress Customizer, all of which rely on versioned assets to push changes out.
- CDNs behave the same way as browsers. On Cloudflare, the default Standard caching level “delivers a different resource each time the query string changes,” which is precisely the behaviour you want: a new
?ver=is a new cache entry. Take the query string away and the CDN has no signal that the file changed. - You get nothing back. Modern speed tests do not score it, Core Web Vitals do not measure it, and Google does not rank on it. The only number that moves is a legacy checklist item in tools that have not been updated.
There is one situation where a query string genuinely hurts: a CDN or proxy that has been configured to ignore query strings entirely. In that case the fix is the CDN setting, not your WordPress URLs, because the same setting is what stops your updates from ever reaching that cache.
Which tools still show the warning
- GTmetrix: the recommendation page is titled “deprecated” and it does not affect your grade.
- PageSpeed Insights and Lighthouse: no such audit exists. The closest is “Serve static assets with an efficient cache policy,” which is about cache lifetime and, if anything, argues for versioned URLs.
- Pingdom Website Speed Test: built on the YSlow rule set, which is roughly twenty years old and no longer maintained, so its recommendations are worth reading with that in mind.
- Hosting dashboards: some hosts bundle a checker that still lists it. It is a checklist item, not a ranking factor, and your host will not penalise you for leaving the query strings alone.
If you still want to remove them: three ways
Some people have a client checklist to satisfy, or a proxy they cannot reconfigure. Every method below does the same thing and carries the same risk, so whichever you pick, clear your page cache afterwards and remember the trade-off the next time a plugin updates and someone reports a broken layout you cannot reproduce.
1. W3 Total Cache
W3 Total Cache still ships the option. Go to Performance > Browser Cache in your dashboard:

Scroll to the general settings and tick “Remove query strings from static resources”, then save and purge the cache.

2. A standalone plugin
If you are not running a caching plugin with the option, the WP Remove Query Strings From Static Resources plugin does only this. It is still maintained, with a 2026 release, though it is a small install base for the reasons above.
After you install and activate it, view the source of your homepage to confirm the ?ver= parameters are gone from CSS and JavaScript URLs.
3. A PHP snippet
The snippet hooks the two filters WordPress runs every script and style URL through, script_loader_src and style_loader_src, and strips the ver and v parameters. Add it through the Code Snippets plugin or a child theme rather than your parent theme’s functions.php:
//Remove Query Strings From Static Resources
function smartwp_remove_query_strings_from_static_resources( $src ) {
if( strpos( $src, '?v=' ) ){
$src = remove_query_arg( 'v', $src );
}
if( strpos( $src, '?ver=' ) ){
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
add_filter( 'script_loader_src', 'smartwp_remove_query_strings_from_static_resources', 999 );
add_filter( 'style_loader_src', 'smartwp_remove_query_strings_from_static_resources', 999 );
It is also on GitHub as a gist. Note that it only strips a version that is the first parameter in the URL, which covers what WordPress itself generates.
WP Rocket and Perfmatters users
If you came here looking for the WP Rocket setting, it is not missing on your install. WP Rocket removed “Remove query strings from static resources” from the File Optimization tab in version 3.6, and Perfmatters removed its equivalent in version 1.6.6. Both companies build performance plugins for a living and decided the option did more harm than good. The earlier version of this guide had a WP Rocket walkthrough with a screenshot; it has been removed because the setting no longer exists.
What to do instead
The performance the old rule was chasing comes from caching properly, not from tidying URLs:
- Serve static files with a long
Cache-Controllifetime. A caching plugin or your host normally sets this; Lighthouse’s audit is the one to satisfy. - Keep the query strings so those long lifetimes are safe. That combination, long cache plus versioned URLs, is the whole point.
- Put the site behind a CDN with the default query-string behaviour, and do not switch it to ignore query strings.
- Spend the time on the things that actually move scores: render-blocking CSS and JavaScript, image sizing, and the rest of our guide to speeding up WordPress. Even disabling the emoji script, small as that saving is, is a real change rather than a cosmetic one.
Frequently asked questions
Is removing query strings from static resources still recommended?
No. Google dropped the rule from PageSpeed Insights in 2014, GTmetrix marks it deprecated, Lighthouse has no audit for it, and both WP Rocket (version 3.6) and Perfmatters (version 1.6.6) removed their options after concluding it changed nothing measurable and could break cache-busting. Leave the query strings in place.
Why does WordPress add ?ver= to CSS and JavaScript files?
It is version-based cache-busting. Plugins and themes pass a version number when they enqueue a file, and WordPress appends it to the URL; when none is given, it appends the WordPress version. Because a new version makes a new URL, browsers and CDNs fetch the updated file after an update instead of serving a cached copy for up to a year.
Does removing query strings improve page speed or SEO?
No. It does not change how fast the files load, modern testing tools do not score it, Core Web Vitals do not measure it, and Google does not use it as a ranking signal. The only thing it can change is a checklist item in an outdated tool.
Will removing query strings break my site?
Not immediately. The risk appears after the next plugin, theme or core update, when browsers and CDNs that cached the old file keep serving it because the URL did not change. Sites using Elementor, Beaver Builder or the Customizer are the most commonly affected, according to Perfmatters, which removed its own option for this reason.
Where did the Remove query strings option go in WP Rocket?
It was removed in WP Rocket 3.6. WP Rocket’s developers measured identical speed results with and without query strings and noted that modern browsers and proxies cache based on headers, not on the presence of a question mark in the URL. There is nothing to re-enable.
Does Cloudflare cache files that have query strings?
Yes. At its default Standard caching level Cloudflare caches a separate copy for each distinct query string, so style.css?ver=4.2.1 and style.css?ver=4.3.0 are cached independently and an update is picked up automatically. That is the behaviour you want. Only the Ignore Query String and No Query String levels treat them differently.
Which speed tools still flag query strings?
GTmetrix shows the item as deprecated and does not grade it. Pingdom’s speed test is built on the twenty-year-old YSlow rules and may still list it. Some hosting dashboards bundle an older checker. PageSpeed Insights, Lighthouse and WebPageTest do not flag it at all.
Bottom line
The query strings on your CSS and JavaScript are not a problem to fix. They are the fix, for a real problem: getting new files to visitors after an update without breaking long-lived caching. The recommendation to remove them was correct for a proxy that was patched in 2008 and has been retired by the tools that popularised it. Leave them alone, cache aggressively, and put the effort into changes that show up in a real measurement.


