When you upload an image to WordPress, the file you selected is usually not the only file that ends up inside the uploads directory.
WordPress can automatically create several smaller versions of the image for different layouts and responsive-image scenarios.
For example, uploading:
landscape.jpg
2400 × 1600
may result in files such as:
landscape.jpg
landscape-150x150.jpg
landscape-300x200.jpg
landscape-768x512.jpg
landscape-1024x683.jpg
A theme or plugin may add even more:
landscape-600x400.jpg
landscape-1200x800.jpg
These generated files are commonly called thumbnails, although WordPress more accurately describes them as image sub-sizes or intermediate image sizes.
The process looks simple from the Media Library, but several systems work together behind the scenes: image-size registration, attachment creation, large-image handling, image editors, resizing and cropping, physical file generation and attachment metadata updates.
This guide explains how WordPress generates image thumbnails from the moment an image is uploaded, what determines which files are created, why some thumbnails are missing and how the generated files become part of the attachment’s metadata.
What WordPress means by a thumbnail
In everyday WordPress usage, the word “thumbnail” is used in two different ways.
The specific thumbnail size
WordPress has a built-in image size called:
thumbnail
which commonly uses dimensions configured under:
Settings
→
Media
A typical configuration is:
150 × 150
cropped
Any generated smaller version of an image
Developers also commonly say “thumbnail” when referring to any derivative created from an uploaded image, such as:
medium
medium_large
large
homepage-card
product-grid
hero
Technically, these are image sub-sizes or intermediate image sizes.
Throughout this guide, “thumbnail generation” refers broadly to WordPress creating these derived image files.
The thumbnail generation process at a glance
A traditional server-side WordPress image upload can be simplified as:
image uploaded
↓
attachment post created
↓
source image inspected
↓
large-image scaling considered
↓
registered image sizes collected
↓
sizes filtered
↓
WordPress image editor loaded
↓
thumbnails resized / cropped
↓
physical files saved
↓
attachment metadata updated
Several Core functions participate in this process.
The most important include:
wp_generate_attachment_metadata()
wp_create_image_subsizes()
_wp_make_subsizes()
wp_get_registered_image_subsizes()
Step 1: the original image is uploaded
The process begins when WordPress receives an image upload.
The original file is normally placed somewhere below:
wp-content/uploads/
If date-based upload folders are enabled, a path may look like:
wp-content/uploads/2026/08/
For example:
wp-content/uploads/2026/08/mountain.jpg
WordPress also creates an attachment record representing that media item in the database.
The Media Library entry and the physical file are related, but they are not the same thing.
Step 2: WordPress generates attachment metadata
A central function in the process is:
wp_generate_attachment_metadata()
For image attachments, this function participates in generating metadata and image sub-sizes.
The metadata can include information such as:
- image width;
- image height;
- relative file path;
- generated image sizes;
- image metadata;
- file-size information.
Conceptually:
attachment
↓
wp_generate_attachment_metadata()
↓
image processing
↓
metadata structure
Step 3: WordPress inspects the source image
Before WordPress can create smaller derivatives, it needs to know what it is working with.
The source image may provide information such as:
width
height
format
orientation
metadata
Suppose the uploaded image is:
4000 × 2667
JPEG
WordPress now knows which registered image sizes are physically possible to generate from that source.
Step 4: WordPress may scale very large images
Before ordinary thumbnail generation, WordPress can apply its large-image handling system.
The relevant filter is:
big_image_size_threshold
Its default threshold is:
2560 pixels
If the image width or height exceeds that threshold, WordPress can create a scaled copy.
Example
Suppose the source is:
6000 × 4000
WordPress may create something similar to:
photo-scaled.jpg
with its longest dimension reduced to approximately:
2560px
That scaled file can become WordPress’s primary working full-size representation.
The untouched original can still be retained
The original uploaded file may remain available separately.
This distinction matters because:
original uploaded file
and:
WordPress full-size working image
may not always refer to the same physical file.
Step 5: WordPress determines the registered image sizes
WordPress needs to know which thumbnails the site currently wants.
The normalized list is available through:
wp_get_registered_image_subsizes()
The list can contain image sizes from:
- WordPress Core;
- the active theme;
- plugins;
- custom code.
Example
thumbnail
150 × 150
crop: true
medium
300 × 300
crop: false
large
1024 × 1024
crop: false
homepage-card
640 × 420
crop: true
The image-size registration system is explained in more depth in How WordPress generates image sizes.
Step 6: plugins and themes can filter the generation list
WordPress does not necessarily generate every globally registered size for every upload.
The filter:
intermediate_image_sizes_advanced
allows developers to change the list of image sizes that will be generated.
Example
add_filter(
'intermediate_image_sizes_advanced',
function ( $sizes ) {
unset(
$sizes['unused-banner']
);
return $sizes;
}
);
If:
unused-banner
is globally registered but removed by this filter, WordPress will not generate that derivative during that processing run.
Step 7: WordPress prepares the image editor
On the traditional server-side path, WordPress works through its image-editor abstraction.
The main image-processing engines commonly available are:
- Imagick;
- GD.
WordPress asks its image editor to open the source file and perform operations such as:
- resize;
- crop;
- format conversion where configured;
- saving generated files.
The higher-level WordPress code therefore does not need to implement every JPEG or PNG transformation itself.
wp_create_image_subsizes()
A particularly important Core function is:
wp_create_image_subsizes()
Its role includes:
- creating image sub-sizes;
- adding generated-size information to the attachment metadata;
- updating that metadata.
It also handles parts of the large-image workflow described earlier.
The process can be visualized as:
source image
↓
wp_create_image_subsizes()
↓
registered sizes
↓
filtered sizes
↓
thumbnail generation
↓
metadata updates
_wp_make_subsizes() performs lower-level generation work
WordPress also contains the lower-level function:
_wp_make_subsizes()
It receives the requested image sizes and works with a WordPress image editor to create the missing derivatives.
Conceptually:
sizes requested:
thumbnail
medium
large
homepage-card
↓
then WordPress processes those sizes and records successful outputs.
How proportional thumbnail resizing works
Not every image size means “create exactly these dimensions.”
When cropping is disabled:
crop = false
WordPress preserves the original aspect ratio.
Example
Source:
1200 × 800
Registered size:
300 × 300
crop: false
The source ratio is:
3:2
So WordPress may produce:
300 × 200
rather than:
300 × 300
The registered dimensions act as boundaries rather than a requirement to distort the image.
How hard-cropped thumbnails work
When:
crop = true
WordPress can crop the image so the resulting file matches the target aspect ratio more closely.
Example
Source:
1200 × 800
Target:
300 × 300
crop: true
WordPress can remove part of the horizontal content and create:
300 × 300
Why themes use cropped sizes
Hard cropping is useful for interfaces that require consistent visual geometry, such as:
- post cards;
- product grids;
- team-member portraits;
- portfolio cards;
- featured content tiles.
Crop position can be customized
A custom size can specify crop alignment.
For example:
add_image_size(
'portrait-card',
600,
800,
array(
'center',
'top'
)
);
This lets WordPress favor the upper part of the source when performing the crop.
That can be useful when faces or other important content usually appear near the top of the image.
Why some thumbnails are not generated
A registered size does not guarantee that WordPress will create a physical file for every attachment.
The source is too small
Suppose the site requests:
hero
1600 × 900
but the uploaded image is:
600 × 400
WordPress generally does not upscale the small source simply to create the larger derivative.
The size was filtered out
A theme or plugin may alter the generation list.
The image editor could not process the file
Possible causes include:
- memory exhaustion;
- corrupt source files;
- unsupported formats;
- GD or Imagick limitations;
- filesystem problems.
The size did not exist when the image was uploaded
If an image was uploaded in:
2023
and a theme adds a new size in:
2026
the old attachment will not automatically gain that thumbnail.
See Regenerating WordPress image thumbnails for the practical fix.
WordPress writes thumbnails beside the source image
Generated image files commonly live in the same upload directory as the attachment’s main image.
For example:
wp-content/uploads/2026/08/
mountain.jpg
mountain-150x150.jpg
mountain-300x200.jpg
mountain-768x512.jpg
mountain-1024x683.jpg
Each derivative is a real physical file.
It is not simply a virtual URL created dynamically when somebody requests the image.
Generated filenames commonly contain dimensions
WordPress derivative filenames frequently follow this pattern:
filename-WIDTHxHEIGHT.extension
For example:
mountain-300x200.jpg
However, developers should not depend on reconstructing these filenames manually.
WordPress already stores the actual generated filename in attachment metadata.
Thumbnail information is added to attachment metadata
Creating the file is only half of the process.
WordPress also needs to know that the file exists.
A simplified attachment metadata structure might look like:
array(
'width' => 2400,
'height' => 1600,
'file' => '2026/08/mountain.jpg',
'sizes' => array(
'thumbnail' => array(
'file' => 'mountain-150x150.jpg',
'width' => 150,
'height' => 150,
),
'medium' => array(
'file' => 'mountain-300x200.jpg',
'width' => 300,
'height' => 200,
),
),
)
This information allows WordPress to later retrieve:
- the correct filename;
- actual dimensions;
- the relevant responsive-image candidates.
Metadata is updated progressively
WordPress’s thumbnail-generation architecture is designed to update image metadata as generated sub-sizes become available.
Conceptually:
thumbnail created
↓
metadata updated
medium created
↓
metadata updated
large created
↓
metadata updated
This is useful because image generation can be resource-intensive.
If a later sub-size fails, WordPress may still retain information about earlier derivatives that were successfully created.
The generated file and its metadata are both important
A thumbnail can be broken in two different ways.
Metadata exists but physical file is missing
WordPress may believe:
medium
→ mountain-300x200.jpg
exists even though the file disappeared during a migration or incomplete restore.
The physical file exists but metadata does not describe it
A historical or manually copied derivative can exist on disk without being part of the attachment’s current metadata.
For normal WordPress operations, the metadata relationship matters.
How WordPress detects missing thumbnails
WordPress provides:
wp_get_missing_image_subsizes()
This compares:
currently registered sizes
against:
sizes recorded in
attachment metadata
and returns the difference.
Example
Registered:
thumbnail
medium
large
homepage-card
Attachment metadata:
thumbnail
medium
Missing:
large
homepage-card
WordPress can generate only missing thumbnails
The function:
wp_update_image_subsizes()
can generate currently registered image sizes that are missing from an attachment.
This is useful because:
generate missing files
is often more efficient than:
regenerate every existing file
How to inspect thumbnails for one attachment
You can use:
wp_get_attachment_metadata()
to inspect the complete metadata structure.
For example:
$metadata =
wp_get_attachment_metadata(
123
);
if (
! empty(
$metadata['sizes']
)
) {
print_r(
$metadata['sizes']
);
}
Use raw debugging output only in a development environment.
Inspecting one specific thumbnail
WordPress also provides:
image_get_intermediate_size()
For example:
$image =
image_get_intermediate_size(
123,
'medium'
);
if ( $image ) {
echo esc_url(
$image['url']
);
}
This can return information such as:
- filename;
- width;
- height;
- path;
- URL.
For a full guide to retrieving derivative URLs, see Finding a specific WordPress image size’s URL.
How WordPress thumbnails support responsive images
The generated files are not created only so themes can manually choose between:
thumbnail
medium
large
They also help power responsive image markup.
WordPress can generate:
srcset
containing multiple candidate images.
For example:
<img
src="mountain-768x512.jpg"
srcset="
mountain-300x200.jpg 300w,
mountain-768x512.jpg 768w,
mountain-1024x683.jpg 1024w
"
sizes="(max-width: 768px) 100vw, 768px"
width="768"
height="512"
alt=""
>
The browser can then choose the most appropriate candidate.
WordPress does not necessarily use every generated thumbnail
A site may have:
10 physical derivatives
for one image, while a particular frontend output uses only:
3 responsive candidates
This is normal.
Generation and frontend selection are separate processes.
A useful distinction is:
registered size
↓
generated thumbnail
↓
available metadata
↓
template request
↓
responsive candidate selection
Thumbnail generation affects storage
Each successfully generated derivative is another physical file.
Suppose a WordPress installation has:
25,000 images
and:
8 generated sizes
That can theoretically produce:
200,000 derivative files
in addition to the original uploads.
Not every attachment will necessarily generate every size, but the multiplication effect can still be substantial.
Theme and plugin changes can leave old thumbnails behind
Imagine Theme A registers:
theme-a-card
400 × 300
Thousands of images are uploaded.
Later, Theme B registers:
theme-b-card
640 × 480
WordPress does not automatically delete every:
theme-a-card
file simply because the theme changed.
Historical thumbnails can therefore accumulate.
Do not delete old thumbnails blindly
An apparently obsolete derivative might still be referenced by:
- old post HTML;
- cached pages;
- external websites;
- newsletters;
- custom fields;
- page-builder data.
Thumbnail generation and thumbnail cleanup should be treated as separate tasks.
Thumbnail generation and regeneration are different
Normal generation occurs when an image is originally processed.
Regeneration occurs later.
Generation
new image
+
current registered sizes
↓
thumbnails generated
Regeneration
existing attachment
+
current registered sizes
↓
thumbnails generated again
or missing sizes created
The practical regeneration workflow is covered in Regenerating WordPress image thumbnails.
The deeper internal behavior is covered in What happens when WordPress regenerates thumbnails.
WordPress 7.1 and client-side thumbnail generation
Recent WordPress versions introduced a significant additional processing path: supported media can be processed in the browser rather than requiring every thumbnail to be encoded by PHP on the server.
That changes where some of the work happens, but not the overall conceptual result.
The workflow can now look more like:
image selected in browser
↓
upload begins
↓
server reports required image sizes
↓
browser generates missing thumbnails
↓
generated files are uploaded
↓
WordPress registers them
↓
attachment metadata is updated
The server can skip ordinary thumbnail generation
On the client-side processing path, the upload request can indicate that the server should not generate image sub-sizes itself.
The browser then handles the derivative generation for the required sizes.
The server reports missing image sizes
After the relevant upload stage, WordPress can expose:
missing_image_sizes
representing thumbnails that still need to be generated.
The client-side media system can then process those required derivatives.
Duplicate dimensions can share one physical file
An interesting optimization in the client-side system concerns image sizes with equivalent output dimensions.
Suppose two registered names effectively produce the same result:
size-a
768 × 1024
size-b
768 × 1024
WordPress does not necessarily need two identical physical files.
The processing system can deduplicate equivalent output dimensions and associate the same generated file with multiple size names.
This prevents useless duplicate images from being created solely because two registrations happen to have different names.
Large-image scaling can also happen client-side
The:
big_image_size_threshold
configuration is also relevant to client-side processing.
If a source exceeds the threshold, the browser can generate the scaled version as part of that workflow.
The final WordPress attachment still follows the same broad concepts:
- source image;
- scaled image where required;
- registered sizes;
- generated thumbnails;
- attachment metadata.
Why client-side processing matters
Moving image work away from PHP can reduce pressure on the server during uploads.
Traditional thumbnail generation can involve:
- large memory allocations;
- CPU-intensive resizing;
- multiple image encodes;
- long-running PHP requests.
Client-side processing can move some of that computational work to the user’s browser.
Not every server-side image hook fires on the client path
This matters for plugin developers.
Some hooks are tied specifically to the server-side WP_Image_Editor process.
If no server-side image editor instance exists, those hooks cannot behave exactly as they did on the traditional path.
Developers building advanced image-processing plugins should therefore consult current WordPress media-processing documentation rather than assuming every upload always passes through identical PHP code.
Existing image-size filters still matter
The newer media-processing architecture continues to respect important WordPress image configuration concepts.
These include settings and filters related to:
- registered intermediate sizes;
- advanced intermediate-size filtering;
- big-image threshold;
- output formats;
- image metadata handling.
The processing location may change, but WordPress still needs to know which derivatives the site expects.
How to see which thumbnails actually exist
One of the most common debugging mistakes is looking at the global size list and assuming every image must contain every listed thumbnail.
That is not true.
TheOneWP Image Sizes List can show the sizes actually generated for an individual attachment.
This makes it useful for questions such as:
Was medium generated?
Does homepage-card exist?
What are its real dimensions?
What is its URL?
Use Image Sizes List after changing image generation
If you modify:
add_image_size()
or change a theme, a useful workflow is:
upload test image
↓
open attachment
↓
inspect generated sizes
↓
verify dimensions
↓
verify URLs
↓
only then regenerate old media
This avoids discovering after processing 40,000 images that the crop configuration was wrong.
Thumbnail generation and image optimization are separate
Creating a:
600 × 400
thumbnail does not automatically mean the resulting file is optimally compressed.
Thumbnail generation answers:
What dimensions should
this derivative use?
Optimization answers:
How efficiently should
those pixels be encoded?
TheOneWP Image Optimizer addresses the optimization side of the workflow.
Generated thumbnails and Core Web Vitals
Correct thumbnail generation can improve frontend performance when WordPress uses a derivative close to the actual display size.
For example:
original:
3000 × 2000
2 MB
card thumbnail:
600 × 400
110 KB
Serving the card thumbnail in a small layout can avoid transferring the full-resolution original.
That can improve page loading, especially when the image contributes to Largest Contentful Paint.
See Core Web Vitals and image weight for the performance side of image delivery.
Generating a thumbnail does not guarantee WordPress will use it
A theme might successfully generate:
homepage-card
600 × 400
but then request:
full
on the frontend.
The correctly generated thumbnail provides no bandwidth benefit if the template ignores it.
You must distinguish between:
generation
and:
selection
How to debug a missing thumbnail
1. Confirm the size is registered
Check the active image-size configuration.
2. Check the original dimensions
The source may simply be too small.
3. Inspect the attachment metadata
Look for the expected entry in:
$metadata['sizes']
4. Check the physical uploads directory
Determine whether the file exists.
5. Check processing errors
Look for:
- PHP memory errors;
- image-library errors;
- filesystem errors;
- unsupported source formats.
6. Check generation filters
A plugin may intentionally suppress the size.
7. Check when the image was uploaded
The attachment may predate the size registration.
Common WordPress thumbnail-generation mistakes
Assuming thumbnail means only 150 × 150
WordPress generates many intermediate image sizes.
Assuming every registered size gets a file
Generation depends on the source and current processing rules.
Assuming a 300 × 300 soft size creates a 300 × 300 image
Aspect ratio is preserved when cropping is disabled.
Adding a custom size after years of uploads and expecting old images to contain it
Existing attachments need regeneration.
Guessing thumbnail filenames
Use WordPress metadata instead.
Ignoring crop behavior
Crop configuration can radically change the generated composition.
Generating many nearly identical sizes
Each registration can increase processing and storage.
Assuming old thumbnail files disappear when a theme changes
Historical files can remain in uploads.
Deleting every unknown thumbnail automatically
Old URLs may still be referenced.
Assuming every thumbnail is always generated server-side
Modern WordPress also supports client-side media-processing workflows.
Assuming generation means optimization
Image dimensions and encoding efficiency are separate concerns.
WordPress thumbnail generation checklist
- Identify the image sizes registered by WordPress Core.
- Identify custom sizes registered by the theme.
- Identify plugin-generated sizes.
- Check width and height constraints.
- Check crop behavior.
- Check crop alignment where relevant.
- Understand the source image dimensions.
- Check the large-image threshold.
- Remember that WordPress generally avoids unnecessary upscaling.
- Check
intermediate_image_sizes_advancedfilters. - Understand which image editor is available.
- Inspect actual generated files.
- Inspect attachment metadata.
- Do not assume every registered size exists for every image.
- Check missing sub-sizes before regenerating everything.
- Regenerate old attachments after changing size definitions.
- Keep thumbnail generation and cleanup as separate tasks.
- Keep thumbnail generation and optimization as separate tasks.
- Verify frontend templates actually request appropriate sizes.
- Account for client-side processing on current WordPress versions.
Related WordPress image guides
Continue with these related guides and tools:
- How WordPress generates image sizes
- Regenerating WordPress image thumbnails
- What happens when WordPress regenerates thumbnails
- Finding a specific WordPress image size’s URL
- Core Web Vitals and image weight
- WebP vs. AVIF vs. JPEG for WordPress
- WordPress image cache-busting explained
- Replacing vs. re-uploading WordPress media
- Image Sizes List
- Image Optimizer
- Media Replace
Final thoughts
WordPress thumbnail generation is best understood as a file-processing pipeline.
The traditional server-side path looks roughly like:
upload original
↓
inspect image
↓
consider large-image scaling
↓
collect registered sizes
↓
filter generation list
↓
load image editor
↓
resize or crop
↓
save derivative
↓
record metadata
Modern WordPress can also move part of that work into the browser through client-side media processing, but the final objective remains the same: create the image derivatives required by the site and register them correctly against the Media Library attachment.
The most important distinction is:
registered thumbnail
≠
generated thumbnail
≠
thumbnail used on frontend
A theme can register an image size that does not exist for an old or undersized attachment.
A thumbnail can exist physically but be ignored by the frontend template.
And a historical derivative can remain on disk long after the code that created it has disappeared.
When debugging WordPress images, follow the process in order: inspect the registered sizes, inspect the source image, inspect the generated attachment metadata, confirm the physical files and finally check what the frontend actually requests.

