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:
- The browser sends a request to your web server
- WordPress PHP scripts load, starting with
index.php - PHP queries the MySQL database to fetch the requested content
- Your theme’s PHP templates combine with the database content
- WordPress generates the final HTML page on-the-fly and sends it to the browser

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 Value | What It Stores |
|---|---|
post | Blog posts |
page | Static pages |
attachment | Media files (images, PDFs, videos) |
revision | Previous versions of posts and pages |
nav_menu_item | Navigation menu entries |
wp_block | Reusable Gutenberg blocks |
wp_template | Block theme templates (WordPress 5.9+) |
wp_navigation | Navigation blocks (WordPress 5.9+) |
custom_css | Custom CSS from the Customizer |
| Custom types | WooCommerce products, portfolio items, etc. |

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:
| Column | Data Type | Purpose |
|---|---|---|
ID | bigint(20) | Unique identifier for each entry |
post_author | bigint(20) | User ID of the author (links to wp_users) |
post_date | datetime | Publish date in site timezone |
post_date_gmt | datetime | Publish date in GMT/UTC |
post_content | longtext | Full content of the post (including Gutenberg block markup) |
post_title | text | Title of the post or page |
post_excerpt | text | Short summary/excerpt |
post_status | varchar(20) | Status: publish, draft, pending, private, trash, auto-draft |
comment_status | varchar(20) | Whether comments are open or closed |
ping_status | varchar(20) | Whether pingbacks and trackbacks are open or closed |
post_password | varchar(255) | Password for password-protected posts |
post_name | varchar(200) | URL slug (e.g., my-first-post) |
to_ping | text | URLs queued for pingback notification |
pinged | text | URLs already pinged |
post_modified | datetime | Last modified date (site timezone) |
post_modified_gmt | datetime | Last modified date (GMT/UTC) |
post_content_filtered | longtext | Filtered/cached version of content |
post_parent | bigint(20) | Parent post ID (used for page hierarchy and attachments) |
guid | varchar(255) | Global unique identifier URL (used in RSS feeds) |
menu_order | int(11) | Sort order for pages and menu items |
post_type | varchar(20) | Content type: post, page, attachment, revision, etc. |
post_mime_type | varchar(100) | MIME type for attachments (image/jpeg, application/pdf) |
comment_count | bigint(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><!– wp:paragraph –></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:
| Column | Purpose |
|---|---|
meta_id | Unique identifier for each meta row |
post_id | Links back to the post’s ID in wp_posts |
meta_key | Name of the metadata field |
meta_value | Value 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 postrank_math_title— SEO title from Rank Mathrank_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:
| Table | Purpose |
|---|---|
wp_posts | All posts, pages, revisions, attachments, menu items, and custom post types |
wp_postmeta | Metadata for posts — custom fields, SEO data, plugin settings |
wp_comments | All comments on posts and pages |
wp_commentmeta | Metadata for comments (spam flags, ratings, etc.) |
wp_users | User accounts — username, email, hashed password, registration date |
wp_usermeta | User metadata — roles, preferences, dashboard settings |
wp_options | Site-wide settings — site title, URL, active plugins, active theme, permalink structure |
wp_links | Blogroll links (deprecated since WordPress 3.5 but the table still exists) |
wp_terms | Categories, tags, and custom taxonomy terms |
wp_termmeta | Metadata for taxonomy terms |
wp_term_taxonomy | Links terms to their taxonomy type (category, post_tag, etc.) |
wp_term_relationships | Associates 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.

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.

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.

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

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

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.