Stop WordPress Compressing Your Images at 82%
WordPress re-encodes every JPEG it generates at quality 82 on a 0–100 scale. That default lives in WP_Image_Editor::get_default_quality() and applies to
Published
WordPress re-encodes every JPEG it generates at quality 82 on a 0–100 scale. That default lives in WP_Image_Editor::get_default_quality() and applies to every derivative WordPress cuts from your upload — thumbnail, medium, medium_large, large, and every extra size your theme registers. For photographs, 82 is a sane trade between file size and artifacts. For screenshots, UI captures, charts, logos, and anything with sharp text or flat color, 82 is visibly destructive: you get mosquito noise crawling around every letter and banding across smooth gradients.
To change it, add one filter and regenerate your thumbnails. To fix screenshots specifically, the better answer is usually to stop handing WordPress a JPEG in the first place.
Where the number 82 actually comes from
WordPress dropped its JPEG default from 90 to 82 back in 4.5 (2016) as a page-weight optimization. The value is returned by get_default_quality() in wp-includes/class-wp-image-editor.php and is read whenever the active editor — WP_Image_Editor_Imagick if your host has Imagick, otherwise WP_Image_Editor_GD — writes a resized file.
The important detail: 82 is applied per derivative size, not once. Upload one image, and WordPress runs it through the encoder multiple times, re-quantizing at quality 82 each pass. The originally uploaded file itself is left untouched if it is under the big-image threshold (2560px on the long edge). If it exceeds that threshold, WordPress produces a re-encoded -scaled.jpg at quality 82 and serves that as the “full” size. So “my full-resolution image looks fine but the version on the page looks smeared” is almost always a srcset picking a quality-82 sub-size or the -scaled file.
How to change the quality
There is one filter to hook. wp_editor_set_quality is the modern, canonical one — it fires for JPEG and WebP and receives the MIME type so you can branch:
add_filter( 'wp_editor_set_quality', function ( $quality, $mime_type ) {
if ( 'image/jpeg' === $mime_type ) {
return 92; // up from 82
}
return $quality;
}, 10, 2 );
Put this in a small mu-plugin (wp-content/mu-plugins/) or a site-specific plugin. functions.php works too, but you lose the setting the moment you switch themes.
You will also see the older jpeg_quality filter recommended. It still fires (WordPress applies it right after wp_editor_set_quality, JPEG-only), but there is no reason to hook both — wp_editor_set_quality covers everything the old one did and more.
One thing everyone forgets: this filter only affects images encoded after it is active. Every thumbnail already sitting in wp-content/uploads was written at 82 and will stay at 82. Regenerate them:
wp media regenerate --yes
If you are not on WP-CLI, the Regenerate Thumbnails plugin does the same thing through the admin.
Before you commit to a number, it is worth seeing what a given quality actually does to your image rather than guessing. Our WordPress JPEG quality tool re-encodes a sample in the browser at every quality level so you can watch the artifacts appear — it makes the difference between 82, 90, and 100 obvious on a screenshot in a way that a number in a config file never will.
The better fix for screenshots and flat graphics
Raising the JPEG number treats the symptom. The actual problem with screenshots is that JPEG is the wrong codec for them. JPEG’s DCT compression is tuned for photographic gradients; it falls apart on the hard black-on-white edges of text and UI chrome, which is exactly why quality 82 looks so much worse on a screenshot than on a photo of a beach.
Upload a PNG instead. WordPress keeps PNG sub-sizes as PNG, and PNG is lossless — the quality filter does not touch it, so there are no artifacts at any size, only clean resampling. For a screenshot, a well-optimized PNG is often smaller than a high-quality JPEG of the same image anyway, because flat color compresses well in PNG and terribly in JPEG.
If you want the smaller files of a lossy format without JPEG’s edge damage, WebP is the middle ground — but you still control its quality through the same wp_editor_set_quality filter shown above, branching on image/webp.
What not to do
Do not set quality to 100 globally. This is the top-voted answer on half the forum threads, and it is wrong. Quality 100 JPEG is not lossless — it still quantizes — but it inflates every photograph on your site by a large margin for no visible gain, dragging down LCP and Core Web Vitals. Raise the number for the format that needs it, or change format for graphics; don’t nuke compression sitewide.
Do not edit class-wp-image-editor.php. Changing the return value of get_default_quality() in core works until the next wp core update silently overwrites it. Use the filter.
Do not disable image sizes to “avoid the compression.” Turning off thumbnail generation doesn’t stop re-encoding — it breaks responsive srcset, so browsers download your full-size image on phones. Different problem, worse outcome.
Do not assume re-uploading fixes existing images. If you set the filter but skip the regenerate step, every old derivative is still quality 82. The filter is forward-looking only.
Do not blame the -scaled file if your images are under 2560px — that path never runs for them. If you are hitting it and want the untouched original served, that is a separate setting; see disabling scaled images.
Still stuck?
If a specific size still looks wrong after regenerating, confirm which file the page is actually serving — open the image in a new tab and check whether the filename ends in a dimension suffix (-1024x768.jpg) or -scaled.jpg. The image sizes inspector shows every derivative WordPress generates from one upload, so you can see exactly which size your srcset is handing to the browser and stop debugging the wrong file.