Where Are WordPress Posts and Pages Stored? [Complete SQL Guide]

Where WordPress Pages Are Stored?

TL;DR: WordPress stores all posts, pages, and custom post types in the wp_posts MySQL database table — not as individual HTML files. Each row holds the title, content, status, author, and timestamps. Related metadata (custom fields, SEO data, featured images) goes into the wp_postmeta table. You can access and query this data through phpMyAdmin or direct SQL commands.

Here’s something that surprised me when I first started building WordPress sites back in 2017: WordPress doesn’t create individual HTML files for your posts and pages.

I assumed every blog post lived as a separate .html file on the server. That’s how basic websites work, right? But WordPress is built on PHP and MySQL, and it works completely differently.

In this guide, I’ll show you exactly where WordPress stores your content in the database, break down every table and column, and share practical SQL queries you can copy-paste to find and manage your posts directly.


How Does WordPress Store Your Content?

WordPress doesn’t generate static HTML files. Instead, it uses a MySQL database (or MariaDB) as its storage engine. When you hit “Publish” on a post or page, WordPress writes a new row in the database — no file is created.

When a visitor opens your site, here’s what happens behind the scenes:

  1. The browser sends a request to your web server
  2. WordPress PHP scripts load, starting with index.php
  3. PHP queries the MySQL database to fetch the requested content
  4. Your theme’s PHP templates combine with the database content
  5. WordPress generates the final HTML page on-the-fly and sends it to the browser
Diagram showing how WordPress dynamically generates pages from database content using PHP and MySQL
WordPress generates pages dynamically — content lives in the database, not in HTML files.

This dynamic approach is what makes WordPress so flexible. You can switch themes, update content, or reorganize your entire site without touching a single file. The trade-off? Every page request hits the database, which is why caching plugins are critical for WordPress speed.


Where Are WordPress Posts Stored in the Database?

All WordPress posts, pages, and custom post types are stored in a single table: wp_posts.

One table handles everything — blog posts, static pages, media attachments, navigation menus, revisions, and custom post types like WooCommerce products. The table name follows the format {prefix}_posts. The default prefix is wp_, but most hosting providers change it to something random like wp3f_posts for security.

The post_type column is what differentiates each type of content:

post_type ValueWhat It Stores
postBlog posts
pageStatic pages
attachmentMedia files (images, PDFs, videos)
revisionPrevious versions of posts and pages
nav_menu_itemNavigation menu entries
wp_blockReusable Gutenberg blocks
wp_templateBlock theme templates (WordPress 5.9+)
wp_navigationNavigation blocks (WordPress 5.9+)
custom_cssCustom CSS from the Customizer
Custom typesWooCommerce products, portfolio items, etc.
The post_type column inside wp_posts table in phpMyAdmin showing post, page, and attachment types
The post_type column in action — one table stores posts, pages, attachments, and more.

If you’ve ever wondered why your database shows thousands of rows when you only have 50 blog posts — this is why. Revisions, attachments, menu items, and reusable blocks all share the same table.


What Columns Does the wp_posts Table Contain?

The wp_posts table has 23 columns. As of WordPress 6.7 (March 2026), here’s every column and what it stores:

ColumnData TypePurpose
IDbigint(20)Unique identifier for each entry
post_authorbigint(20)User ID of the author (links to wp_users)
post_datedatetimePublish date in site timezone
post_date_gmtdatetimePublish date in GMT/UTC
post_contentlongtextFull content of the post (including Gutenberg block markup)
post_titletextTitle of the post or page
post_excerpttextShort summary/excerpt
post_statusvarchar(20)Status: publish, draft, pending, private, trash, auto-draft
comment_statusvarchar(20)Whether comments are open or closed
ping_statusvarchar(20)Whether pingbacks and trackbacks are open or closed
post_passwordvarchar(255)Password for password-protected posts
post_namevarchar(200)URL slug (e.g., my-first-post)
to_pingtextURLs queued for pingback notification
pingedtextURLs already pinged
post_modifieddatetimeLast modified date (site timezone)
post_modified_gmtdatetimeLast modified date (GMT/UTC)
post_content_filteredlongtextFiltered/cached version of content
post_parentbigint(20)Parent post ID (used for page hierarchy and attachments)
guidvarchar(255)Global unique identifier URL (used in RSS feeds)
menu_orderint(11)Sort order for pages and menu items
post_typevarchar(20)Content type: post, page, attachment, revision, etc.
post_mime_typevarchar(100)MIME type for attachments (image/jpeg, application/pdf)
comment_countbigint(20)Total number of comments on the post

The columns you’ll interact with most are post_content (your actual content), post_title, post_status, post_type, and post_name (the URL slug).

<strong>Gutenberg Tip:</strong> If you’re using the block editor, the <code>post_content</code> column stores your content as HTML wrapped in block comment markers like <code>&lt;!– wp:paragraph –&gt;</code>. That’s how WordPress maps each block in the editor to the saved content.


Where Is Post Metadata Stored?

The wp_posts table holds core content, but everything else — custom fields, SEO settings, featured images, plugin data — lives in the wp_postmeta table.

It has a simple 4-column structure:

ColumnPurpose
meta_idUnique identifier for each meta row
post_idLinks back to the post’s ID in wp_posts
meta_keyName of the metadata field
meta_valueValue of the field

A single blog post can easily have 20-50+ rows in wp_postmeta, depending on your plugins. Here are common meta_key values you’ll see:

  • _thumbnail_id — The featured image attachment ID
  • _edit_lock — Prevents two people from editing the same post
  • _edit_last — User ID of the last person who edited the post
  • rank_math_title — SEO title from Rank Math
  • rank_math_description — SEO meta description
  • _wp_page_template — Custom page template file

This flexible key-value design is what makes WordPress so extensible. Any plugin can store data for any post without modifying the database structure — it just adds rows to wp_postmeta.


What Are All the Default WordPress Database Tables?

A fresh WordPress 6.7 installation creates 12 default tables. Here’s what each one does:

TablePurpose
wp_postsAll posts, pages, revisions, attachments, menu items, and custom post types
wp_postmetaMetadata for posts — custom fields, SEO data, plugin settings
wp_commentsAll comments on posts and pages
wp_commentmetaMetadata for comments (spam flags, ratings, etc.)
wp_usersUser accounts — username, email, hashed password, registration date
wp_usermetaUser metadata — roles, preferences, dashboard settings
wp_optionsSite-wide settings — site title, URL, active plugins, active theme, permalink structure
wp_linksBlogroll links (deprecated since WordPress 3.5 but the table still exists)
wp_termsCategories, tags, and custom taxonomy terms
wp_termmetaMetadata for taxonomy terms
wp_term_taxonomyLinks terms to their taxonomy type (category, post_tag, etc.)
wp_term_relationshipsAssociates posts with their categories and tags

Your database will likely have more than 12 tables. Plugins add their own — WooCommerce alone creates 14+ tables. That’s completely normal.

The wp_options table deserves a special mention. It stores everything from your site title and permalink structure to active plugins and widget configurations. When I’m debugging a WordPress issue, this is usually the second table I check after wp_posts.


How to Access Your WordPress Database via phpMyAdmin

phpMyAdmin comes pre-installed with most web hosting providers. Here’s how to access your WordPress database step by step:

Step 1: Log into your hosting control panel (cPanel, Plesk, or your host’s custom panel).

Step 2: Find phpMyAdmin under the Databases section and click it.

cPanel dashboard showing the phpMyAdmin option under the Databases section
phpMyAdmin is located in the Databases section of your cPanel dashboard.

Step 3: You’ll see all databases listed in the left sidebar. Click your WordPress database name. Not sure which one it is? Check the DB_NAME constant in your wp-config.php file.

phpMyAdmin interface showing WordPress database tables including wp_posts where all content is stored
All your WordPress database tables displayed in phpMyAdmin — wp_posts is where your content lives.

Step 4: Click on {prefix}_posts to browse all your posts, pages, and other content types.

<strong>⚠ Warning:</strong> Always create a full database backup before editing anything in phpMyAdmin. Changes are immediate and there’s no undo button. I’ve broken a site before by running a careless UPDATE query — don’t make the same mistake.


Useful SQL Queries to Find and Manage Your Posts

These are SQL queries I regularly use when managing WordPress databases. You can run them in phpMyAdmin’s SQL tab. Replace wp_ with your actual table prefix.

Find All Published Blog Posts

SELECT ID, post_title, post_date, post_name 
FROM wp_posts 
WHERE post_type = 'post' 
AND post_status = 'publish' 
ORDER BY post_date DESC;

Find All Pages

SELECT ID, post_title, post_name, post_status 
FROM wp_posts 
WHERE post_type = 'page' 
ORDER BY post_title ASC;

Search Posts by Keyword in Content

SELECT ID, post_title, post_date 
FROM wp_posts 
WHERE post_content LIKE '%your-keyword%' 
AND post_type = 'post' 
AND post_status = 'publish';

Find Posts by a Specific Author

SELECT p.ID, p.post_title, u.display_name 
FROM wp_posts p 
JOIN wp_users u ON p.post_author = u.ID 
WHERE p.post_type = 'post' 
AND p.post_status = 'publish';

Count All Content by Post Type

SELECT post_type, COUNT(*) as total 
FROM wp_posts 
GROUP BY post_type 
ORDER BY total DESC;

This last query is particularly useful. When I run it on my own databases, I’m always surprised by how many revision entries pile up. Hundreds of revisions for a site with just 100 posts is common.

View All Metadata for a Specific Post

SELECT meta_key, meta_value 
FROM wp_postmeta 
WHERE post_id = 123;

Replace 123 with the actual post ID. You can find post IDs by hovering over a post title in your WordPress dashboard — the ID appears in the URL.


How to Backup Your WordPress SQL Database

Before making any database changes, create a backup. It takes 30 seconds through phpMyAdmin:

Step 1: Open phpMyAdmin and select your WordPress database from the left sidebar.

Step 2: Click the Export tab at the top navigation bar.

phpMyAdmin Export tab showing options to backup your WordPress database as an SQL file
Click the Export tab to start backing up your database.

Step 3: Choose Quick as the export method and SQL as the format. Click Go.

phpMyAdmin export screen with Quick method and SQL format selected for WordPress database backup
The Quick export method with SQL format is the fastest way to create a full database backup.

The .sql file downloads immediately. This file contains your entire database structure and data. If anything breaks, you can import it back through phpMyAdmin’s Import tab.

For automated backups, I use UpdraftPlus on all my WordPress sites. It backs up both files and the database to cloud storage on a schedule — and it’s saved me more than once.


Where Are WordPress Files Stored? (Directory Structure)

Your content lives in the database, but WordPress also relies on files for themes, plugins, and media uploads. Here’s the directory layout:

public_html/
├── wp-admin/           → Admin dashboard files
├── wp-includes/        → Core WordPress libraries
├── wp-content/
│   ├── themes/        → Installed themes
│   ├── plugins/       → Installed plugins
│   ├── uploads/       → Media (images, PDFs, videos)
│   │   └── 2026/03/   → Organized by year/month
│   └── cache/         → Cached files
├── wp-config.php       → Database credentials & settings
├── .htaccess           → Server rewrite rules
└── index.php           → Entry point for all requests
WordPress file directory structure in cPanel File Manager showing wp-admin, wp-content, wp-includes folders and wp-config.php
The WordPress file system in cPanel’s File Manager — wp-content holds your themes, plugins, and uploads.

The wp-config.php file is particularly important — it stores your database connection details (name, username, password, host, and table prefix). If you ever need to find which database your site uses, check this file first.

The wp-content/uploads/ folder is the only directory that keeps growing. Every image you upload through the media library gets saved here. The database stores a reference to the file (as an attachment post type in wp_posts), but the actual file itself lives in this folder.


Frequently Asked Questions

Are WordPress pages stored as HTML files?

No. WordPress stores pages in the wp_posts MySQL database table, not as static HTML files. When a visitor requests a page, WordPress dynamically generates the HTML by pulling content from the database and combining it with your theme’s PHP templates.

Can I edit WordPress posts directly in the database?

Yes, you can edit posts through phpMyAdmin by modifying the post_content column in wp_posts. However, always create a backup first. Direct database edits skip WordPress hooks and validation, which can break formatting, plugins, or SEO settings.

What happens if I delete a row from wp_posts?

Deleting a row permanently removes that post, page, or attachment and all its associated metadata from wp_postmeta. Unlike trashing from the WordPress dashboard, a direct database deletion is irreversible. Always backup your database before running DELETE queries.

Where is the WordPress database located on the server?

The MySQL database is managed by the database server (not stored as a file you can browse). Connection details are in your wp-config.php file — look for DB_NAME, DB_USER, DB_PASSWORD, and DB_HOST. Access it through phpMyAdmin or command-line MySQL.

How do I find the table prefix for my WordPress site?

Open your wp-config.php file and look for the line $table_prefix = 'wp_';. The value between the quotes is your prefix. Most security plugins and hosting providers change this from the default wp_ to something random like wp3f_.

Does WordPress store images in the database?

Not the image files themselves. WordPress stores image files in the wp-content/uploads/ directory on your server. The database stores a reference to each image as an attachment post type in wp_posts, along with metadata (dimensions, alt text, file path) in wp_postmeta.

How do I convert a WordPress post to a page in the database?

You can change the post_type value from ‘post’ to ‘page’ in the wp_posts table. But a safer method is to use a plugin or WordPress’s built-in tools to convert posts to pages — this preserves SEO settings and URL redirects.


Summing Up!

WordPress stores all your posts, pages, and custom post types in the wp_posts MySQL database table — not as individual HTML files. The wp_postmeta table handles everything else: custom fields, SEO data, featured images, and plugin settings. Together with 10 other default tables, this forms the backbone of every WordPress site.

For most WordPress users, you’ll never need to touch the database directly — the admin dashboard handles everything. But if you’re migrating sites, debugging issues, or doing bulk content updates, knowing your way around phpMyAdmin and basic SQL queries is a genuine superpower.

Bookmark the SQL queries from this guide. They’ve saved me hours over the years, and they’ll do the same for you. And whatever you do — always backup your database before running any direct queries.

Sunny Kumar
Sunny Kumar is the founder of TheGuideX. He writes about SEO, WordPress, cloud computing, and blogging — sharing hands-on experience and honest reviews.