Skip to content

Where Are Images Stored in WordPress? Files and Database Explained

Where Are Images Stored in WordPress? Files and Database Explained

Where are images stored in WordPress? The files live in the wp-content/uploads folder on your server, and the database keeps one record for each image.

We checked every claim in this guide on a WordPress 7.1.3 test site in October 2026. We uploaded a 3200 pixel photo, read the database rows in phpMyAdmin, and ran the URL functions in code.

Below you will see the uploads folder and every image size WordPress makes. You will also see the wp_posts and wp_postmeta rows, how a URL gets built, and a safe way to find where an image is used.

Where Are Images Stored in WordPress?

Where are images stored in WordPress? The picture files sit in the wp-content/uploads folder of your hosting account. The database keeps only the records about those files, in the wp_posts and wp_postmeta tables, and it never holds the pictures themselves.

Think of the folder as the shelf and the database as the catalog card. The card says what the file is called, where it sits, how big it is, and what its alt text says. Without the card, the Media Library cannot list the image, even though the file is still on the shelf.

Where are images stored in WordPress: files in uploads and records in the database

Note: Some themes and plugins keep their own images in their own folders under wp-content. This guide covers images you add through the Media Library, which all go to uploads.

Where Are Image Files Stored on the Server?

Every file you add through the Media Library goes into wp-content/uploads, grouped into folders by year and month. An image uploaded in October 2026 lands in wp-content/uploads/2026/10/. You can open that folder over FTP or in your host’s file manager.

The folder layout comes from one checkbox. In Settings > Media the option “Organize my uploads into month- and year-based folders” controls it, and WordPress turns it on by default. We checked this on the test site, where the option was set to 1.

To see an image’s file name without opening a file manager, use the Media Library. Click an image and the Attachment details panel lists the file name, file type, size and dimensions. For a large photo it also shows an Original image link, which we explain in the next section.

WordPress Media Library attachment details showing file name and original image

Themes and plugins should not guess the image directory WordPress uses. The wp_upload_dir() function returns it for you. Its array includes path, url, subdir, basedir and baseurl, and on our test site basedir pointed at the wp-content/uploads folder and subdir at /2026/10.

Use basedir when you need a path on disk, and baseurl when you need a web address. Hard-coded paths break the day a site moves to a host with a different layout. They also break when someone changes the upload folder, as shown in the section on changing it below.

Where does WordPress store images that ship with a theme? Not in uploads. They sit inside the theme folder, and you build their address with get_theme_file_uri().

On our test site, bloginfo( 'template_directory' ) printed the theme folder address and get_template_directory_uri() printed the same one.

So a logo in a theme’s images folder is a theme file, while a photo you add in the Media Library is an upload.

Which WordPress Image Sizes Does an Upload Create?

WordPress makes six smaller copies of a large photo, and for photos over 2560 pixels it also makes a scaled copy. Our test upload of a 3200 by 2133 pixel JPEG produced eight files in total. That count includes the original.

The six smaller copies come from the registered WordPress image sizes. Those are thumbnail at 150 by 150, medium at 300, medium_large at 768 and large at 1024. The last two are the 1536 and 2048 sizes.

Each file name gets its dimensions added (for example mountain-lake-1024×683.jpg).

WordPress image sizes=

The scaled copy needs more explanation. Since WordPress 5.3, any image taller or wider than 2560 pixels is scaled down to that limit.

The original file is kept in the uploads folder. The scaled file gets a -scaled suffix. Your Media Library now points at mountain-lake-scaled.jpg instead of mountain-lake.jpg.

The original stays on disk and its file name goes into the image meta under original_image. That is why the Attachment details panel showed an Original image link. A filter called big_image_size_threshold changes the 2560 limit.

Smaller photos skip the scaled copy. Our 1200 by 800 test photo made only the thumbnail, medium, medium_large and large files, and its file name stayed team-photo.jpg.

Tip: A theme or plugin can register extra sizes with add_image_size(). On our test site a 1200 by 400 size added one more file to each new upload.

Where Are Images Stored in the WordPress Database?

WordPress stores every image as one row in the wp_posts table, with the post_type column set to attachment. The row holds the title, the mime type, the date and the guid. The extra details, such as the file path, go into the wp_postmeta table.

Run a query for attachments and you see this on any site. Our test site showed one row per image, with post_type attachment and post_mime_type image/jpeg. If you need a refresher on the other tables, our guide to the default WordPress database tables lists all of them.

WordPress attachment rows in the wp_posts table

Notice the guid column in that result. It holds the full web address the image had on the day of the upload. It is meant as an identifier and not as a live link. A later section shows why that matters.

The wp_posts table has no column made for picture data. Its columns hold text, numbers and dates. WordPress itself never writes image data into any of its tables.

What Does wp_postmeta Store for Each Image?

The wp_postmeta table stores the file path, the sizes and the alt text for each image. Each one is a key and value pair tied to the attachment ID. The key _wp_attached_file holds the path, _wp_attachment_metadata holds the sizes, and _wp_attachment_image_alt holds the alt text.

On our test site the attachment with ID 7 had exactly those three rows. The first value was 2026/10/mountain-lake-scaled.jpg, a path relative to the uploads folder. That is the file WordPress treats as the main image.

WordPress attachment meta rows in the wp_postmeta table

The _wp_attachment_metadata value is a long serialized array. It lists the width, the height, the file path, the file size, the original_image name, and one entry for each smaller size. Do not edit it by hand, because one wrong character breaks the whole value.

A featured image works differently. When you set one, WordPress adds a _thumbnail_id row to the post’s own meta, and the value is the attachment ID. That row is the link that connects a post to its image.

The image settings themselves live in the wp_options table. On our test site the options thumbnail_size_w and large_size_w held 150 and 1024. Those options feed the sizes of new uploads.

How Does WordPress Build an Image URL?

WordPress builds an image URL from the _wp_attached_file value and your current upload address. It does not read the guid column. After we changed the site address in our test, wp_get_attachment_url() returned the new domain while the guid kept the old one.

Many guides claim that wp_get_attachment_url() reads the guid. It does not, unless nothing else works.

The WordPress source falls back to the guid only when the other methods fail. A comment in that code says relying on the guid is not recommended.

WordPress guid versus wp_get_attachment_url after a domain move

Here is what we ran. We uploaded an image while the site address was example.com and then changed the site address to newsite.example.

The function returned https://newsite.example/wp-content/uploads/2026/10/mountain-lake-scaled.jpg. The guid still said https://example.com/wp-content/uploads/2026/10/mountain-lake.jpg.

Two more details came out of the test. When we deleted the _wp_attached_file row on a spare image, the function fell back to the guid and returned the old address. And when we hooked the upload_dir filter to a CDN address, the function returned the CDN address too.

Never rewrite guid values during a move, and never read them in your own code. Use wp_get_attachment_url() for the file, and wp_get_attachment_image_url() when you need a certain size.

How Can You Change the Image Upload Folder?

You can move the uploads folder by defining the UPLOADS constant in the wp-config.php file or by filtering upload_dir in code. The WordPress wp-config documentation says the UPLOADS path is relative to ABSPATH and cannot be absolute. It always starts from the site root.

We tested the constant on our site. With define( ‘UPLOADS’, ‘media’ ), wp_upload_dir() returned the media folder at the site root, and wp_get_attachment_url() returned a media address. The files already uploaded did not move, but their URLs followed the new folder. An existing site needs a copy of the old files.

define( 'UPLOADS', 'media' );

The upload_dir filter works in code and can also change the base address. It suits sites that serve files from a CDN host. Since the function reads the filtered address, our test image came back with the CDN path, while the guid stayed unchanged.

Change the folder before you build the site. After that, a move needs a file copy, a database check, and a test of every image on the pages you care about.

How to Find Where an Image Is Used in WordPress

To find where an image is used, look up its attachment ID and then search the featured image meta and the post content. WordPress has no built-in list of the places an image appears. Two short SELECT queries cover posts, pages and featured images.

The queries below only read data and change nothing. Still, take a backup first and swap wp_ for your own table prefix if it differs. Our guide on the WordPress database prefix explains where to find yours.

  1. Find the ID: Open the image in the Media Library. The address ends in item=7, where 7 is the attachment ID, and the Edit more details link shows it as post=7.
  2. Search featured images: Look for posts whose _thumbnail_id meta holds that ID. This finds posts that use the image as the featured image.
  3. Search post content: Search the content for the file name without its size suffix. Posts store sized addresses like mountain-lake-1024×683.jpg. The base name mountain-lake matches every size.
    SQL query that finds where a WordPress image is used

Here is the query behind that result:

SELECT ID, post_title, 'featured image' AS found_in
FROM wp_posts
WHERE ID IN (
  SELECT post_id FROM wp_postmeta
  WHERE meta_key = '_thumbnail_id' AND meta_value = 7
)
UNION
SELECT ID, post_title, 'post content'
FROM wp_posts
WHERE post_type IN ('post', 'page')
  AND post_status = 'publish'
  AND post_content LIKE '%mountain-lake%';

Search by the file name and not by the ID in the content. A search for wp-image-7 also matches wp-image-70 and wp-image-712.

This check has limits because it looks at published posts and pages only. Widgets, theme settings and custom fields keep addresses in other tables. A result of zero rows does not prove an image is unused. Run the same LIKE pattern against wp_options and wp_postmeta before you delete anything.

Warning: Deleting an image permanently removes the file and every size. We ran that on a spare image and all of its files were gone from the folder.

What Should You Back Up and What Breaks When Images Go Missing?

Back up both the uploads folder and the database, because each holds half of an image. The folder holds the files, and the database holds the records that tell WordPress those files exist. A backup of one side restores broken images.

We tested both failures on the test site.

When we deleted a file from the folder by hand, the record stayed in the database. The wp_get_attachment_url() function still returned the address of the missing file. When we deleted only the database row, the files stayed on disk, but WordPress could no longer see them.

The second case also leaves junk behind. Our raw row delete left two orphaned wp_postmeta rows for that image. Deleting through the Media Library avoids both problems, because it removes the row, the meta and the files together.

Moving a site follows the same rule. Copy the whole uploads folder, import the database, and fix the site address. If a move leaves images broken, our WooCommerce database backup guide shows how to take a clean copy first.

If you also care about image weight, our guides on WordPress image optimization and how to resize WordPress images are the next step. Alt text lives in the same wp_postmeta table. Our guide to adding alt tags to images in WordPress shows how to fill it.

Conclusion

Where are images stored in WordPress? The files sit in wp-content/uploads, and the records sit in wp_posts and wp_postmeta. The database never holds the picture, and the guid column is not the source of the image URL.

Keep three rules in mind.

Back up the folder and the database together. Build URLs with wp_get_attachment_url() and wp_upload_dir(). Search by file name when you need to know where an image is used.

If a site move or a broken Media Library is eating your week, our team can take it on through our WordPress migration services.

Frequently Asked Questions (FAQs)

Q1. Are WordPress images stored in the database?

No. The files are stored in the wp-content/uploads folder. The database only stores a record for each image, in wp_posts, plus its path, sizes and alt text in wp_postmeta.

The file sits in the uploads folder like any other image. The link to it is a _thumbnail_id row in wp_postmeta on the post, and its value is the image’s attachment ID.

Q3. Why does my image file name end in -scaled?

WordPress scales any upload larger than 2560 pixels down to that size, and adds -scaled to the new file name. It keeps your original file and records its name in the image meta as original_image.

Q4. Where are WordPress posts and pages stored?

Posts and pages are rows in the wp_posts table. The post_type column says which is which, with post for posts, page for pages and attachment for media files.

Q5. Where is the WordPress database itself stored?

The database lives on your host’s MySQL or MariaDB server, in that server’s data directory. The wp-config.php file only holds the connection details, such as DB_NAME for the database and DB_HOST for the server.

Q6. Can I move the uploads folder to another location?

Yes. Define the UPLOADS constant in wp-config.php with a path relative to the site root, or filter upload_dir in code. Copy the existing files to the new folder yourself, because WordPress does not move them.

Yash Kapoor
Yash Kapoor

Yash Kapoor is the founder and WordPress expert at DevDiggers, where he builds WordPress and WooCommerce plugins for loyalty programs, point-of-sale systems, digital wallets and affiliate management. He writes about developer tools, site performance and the technical side of running a WordPress store. He draws on years of building and maintaining production plugin codebases.

Leave a Reply

Your email address will not be published. Required fields are marked *