Opens in a new tab
  1. Home
  2. Guides
  3. System
System guide

How WordPress generates image thumbnails

Learn how WordPress turns uploaded images into thumbnail files, including registered sizes, cropping, large-image scaling, metadata and client-side processing.

  • Updated September 2, 2026
  • 21 min read
  • WordPress guide

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_advanced filters.
  • 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:

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.

Simplify your WordPress stack

A modular WordPress toolkit. 104 focused tools.

Ultimately, you can build cleaner workflows, maintain fewer plugins and enable only the features each website actually needs.