To check a WordPress database’s charset and collation, run wp db query "SELECT @@character_set_database, @@collation_database;" for the database default, then query information_schema.TABLES for each table, because tables can differ from the default. A modern site should use utf8mb4, with DB_CHARSET set to utf8mb4 and DB_COLLATE left empty.
This guide comes from a note in my own hosting support runbook, and it’s a check I make before migrations. Below are the exact commands I use, what each result means, and the one mistake that catches most people: trusting wp-config.php instead of the database itself.
What should DB_CHARSET and DB_COLLATE be in wp-config.php?
For any current WordPress install, this is what I put in wp-config.php:
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
DB_CHARSET sets the character set of WordPress’s database connection, and the charset WordPress uses when it creates tables. DB_COLLATE sets the collation, which controls how text is sorted and compared. Leaving DB_COLLATE empty is deliberate: WordPress then picks the best collation the server supports.
You can see that logic in core. In WordPress 7.1, wpdb::determine_charset() does three things:
- If
DB_CHARSETisutf8, it upgrades it toutf8mb4. - If the charset is
utf8mb4andDB_COLLATEis empty (or the oldutf8_general_ci), it usesutf8mb4_unicode_ci. - If the server supports it, it upgrades
utf8mb4_unicode_citoutf8mb4_unicode_520_ci.
I’ve seen this on a real site. One WordPress site I run still has define( 'DB_CHARSET', 'utf8' ); in its wp-config.php, yet WordPress connects with utf8mb4 and utf8mb4_unicode_520_ci, and its wp_posts table uses that collation. WordPress corrected the old value at runtime. That’s convenient, but it also shows why the config file alone tells you very little.
Why utf8mb4 and not utf8?
In MySQL, utf8 is not full UTF-8. It’s an alias for utf8mb3, which stores at most three bytes per character. Emoji and some less common characters need four bytes, so a utf8mb3 column can’t store them. utf8mb4 stores the full range.
The MySQL 8.4 reference manual says utf8mb3 is deprecated and recommends utf8mb4 for all new applications. MariaDB servers report the same split; on MariaDB 11 you’ll see collation names such as utf8mb3_uca1400_ai_ci and utf8mb4_uca1400_ai_ci.
There’s one side effect worth knowing. Four bytes per character makes indexes larger, so WordPress core limits indexed text columns to 191 characters ($max_index_length = 191 in wp-admin/includes/schema.php). That’s why keys like meta_key are indexed on a 191-character prefix: 191 times 4 bytes stays under the 767-byte index limit of older InnoDB setups.
Is blog_charset = UTF-8 in wp_options a problem?
No. When you look through a database dump you’ll often see a row like this in wp_options:
(30,'blog_charset','UTF-8','yes')
That’s normal. blog_charset and DB_CHARSET work at different layers and don’t need the same literal value:
blog_charsetis the charset WordPress declares for its output. Core uses it to build theContent-Typeheader, for exampletext/html; charset=UTF-8.DB_CHARSETis the charset of the database connection and of the tables WordPress creates.
UTF-8 is the web’s name for the encoding, and utf8mb4 is MySQL’s name for the full version of it. They describe the same thing.
How do I check the real database charset and collation?
Don’t rely only on DB_CHARSET and DB_COLLATE in wp-config.php. Ask the database what it’s actually using:
wp db query "SELECT @@character_set_database, @@collation_database;"
A typical modern result looks like this:
@@character_set_database @@collation_database
utf8mb4 utf8mb4_general_ci
Older sites may return:
latin1 latin1_swedish_ci
This query is read-only, so it’s safe on a live site. Keep in mind what it measures: the database’s default, which applies to new tables created without an explicit charset. It says nothing certain about the tables you already have.
Check table-level collations
The database default doesn’t tell the full story, because each table can have its own collation. List them all:
wp db query "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME;"
When I ran a grouped version of this query on this blog, the database default is latin1_swedish_ci, yet 55 of its 62 tables are utf8mb4_unicode_520_ci. The other seven are plugin tables: five are latin1_swedish_ci and two are utf8mb3_uca1400_ai_ci. Checking only the database default would have given me the wrong picture in both directions.
To count tables per collation, which is quicker to read on a large site:
wp db query "SELECT TABLE_COLLATION, COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() GROUP BY TABLE_COLLATION;"
For a single table:
wp db query "SHOW TABLE STATUS LIKE 'wp_posts';"
The Collation column in that output is the one you want. If you need to go further, inspect the column collations too, since a column can override its table:
wp db query "SHOW FULL COLUMNS FROM wp_posts;"
Adjust the wp_ prefix if the site uses a custom table prefix (wp config get table_prefix shows it).
The quick check from my runbook
These four commands compare the WordPress settings with the database default in a few seconds. Follow them with the table-level query above when the results disagree or a migration is coming:
wp option get blog_charset
wp config get DB_CHARSET
wp config get DB_COLLATE
wp db query "SELECT @@character_set_database, @@collation_database;"
On a typical modern WordPress site the output is close to this (the empty line is DB_COLLATE):
UTF-8
utf8mb4
utf8mb4 utf8mb4_general_ci
One catch on managed hosting. wp config get reads the wp-config.php file, so if the host defines the constants somewhere else, it fails with “The constant or variable ‘DB_CHARSET’ is not defined in the ‘wp-config.php’ file.” That happens on this blog’s host. In that case, ask the running WordPress which charset and collation its connection actually uses, after its own corrections:
wp eval 'global $wpdb; echo $wpdb->charset, " ", $wpdb->collate, PHP_EOL;'
Why does the charset matter before a migration?
This is where the check pays off. If the source and destination databases use different character sets, the export and import must handle the conversion, or text gets garbled. The classic symptom is mojibake: é showing up as é, curly quotes turning into strings like ’, and emoji replaced by question marks.
Before moving a site, compare three things on both servers: the database default, the table collations, and the WordPress settings. Then make the export charset explicit instead of trusting client defaults. wp db export passes extra flags straight to mysqldump:
wp db export site.sql --default-character-set=utf8mb4
Check what the dump declares before importing it:
grep -m1 'SET NAMES' site.sql
You should see /*!40101 SET NAMES utf8mb4 */;. Each CREATE TABLE statement in the dump also carries its own DEFAULT CHARSET and COLLATE, so the tables arrive with the collations they had at the source. wp db import accepts the same kind of pass-through flag for the mysql client:
wp db import site.sql --default-character-set=utf8mb4
Two safety rules. Keep the original export untouched until the migrated site is verified, so you can always import it again. And note that wp db import runs whatever is in the file: a default wp db export dump includes DROP TABLE IF EXISTS for each table, so take a backup of the destination first if it holds anything you care about. If the core files themselves look damaged after a move, my guide on reinstalling WordPress shows three ways to replace them without touching your content.
Should I convert old latin1 tables to utf8mb4?
Not blindly, and not on a live site first. WordPress did convert existing tables to utf8mb4 once, in the database upgrades that shipped with versions 4.2 and 4.3, but only in a narrow case. Its maybe_convert_table_to_utf8mb4() function skips any table that has a column outside utf8 or utf8mb4. A latin1 table is left exactly as it is. That’s why old latin1 plugin tables can survive for years next to utf8mb4 core tables.
The caution is sensible. A latin1 column sometimes holds bytes that were really UTF-8, written by an application whose connection was set to latin1. An ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 would then encode that text a second time and garble it. Before any conversion:
- Export the database and confirm the file is complete (size, and a
CREATE TABLEfor every table). - Run the conversion on a staging copy, not production.
- Compare real content on staging: accented names, curly quotes, and any non-Latin text the site uses.
- Only then repeat it on production, and keep the export as your rollback.
If the mixed tables cause no errors and the content displays correctly, leaving them alone is a valid choice. Mixed collations become a real problem mainly when a query compares or joins columns with incompatible collations, which MySQL rejects with an “Illegal mix of collations” error.
Charset checks belong in the same toolkit as other read-only server diagnostics. If you’re tracing who changed a file rather than what’s in the database, see how I use auditd to trace file changes on Ubuntu. And if a migration needs a server cut off from an old endpoint while you test, blocking outbound traffic to one IP with iptables is the quickest way.
Quick reference
| What you want to know | Command |
|---|---|
| Output charset WordPress declares | wp option get blog_charset |
| Charset in wp-config.php | wp config get DB_CHARSET |
| Collation in wp-config.php | wp config get DB_COLLATE |
| Charset and collation WordPress actually uses | wp eval 'global $wpdb; echo $wpdb->charset, " ", $wpdb->collate, PHP_EOL;' |
| Database default | wp db query "SELECT @@character_set_database, @@collation_database;" |
| Every table’s collation | wp db query "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME;" |
| One table | wp db query "SHOW TABLE STATUS LIKE 'wp_posts';" |
| Column collations | wp db query "SHOW FULL COLUMNS FROM wp_posts;" |
| Export with an explicit charset | wp db export site.sql --default-character-set=utf8mb4 |
FAQ
What is the best collation for WordPress?
Leave DB_COLLATE empty and let WordPress choose. With utf8mb4 it picks utf8mb4_unicode_520_ci when the server supports it, and utf8mb4_unicode_ci otherwise. Set a collation by hand only if you have a specific sorting requirement.
Why does my database say latin1 when WordPress works fine?
The database default only applies to new tables created without an explicit charset. WordPress creates its tables with its own charset, so the core tables can be utf8mb4 even when the default is latin1. Check the table collations to see what you really have.
Is it safe to change DB_CHARSET on an existing site?
Changing utf8 to utf8mb4 is safe, because current WordPress already uses utf8mb4 in that case. Changing it to a different charset, such as from latin1, changes how text is read and written over the connection and can garble existing content. Test that on a staging copy with a full export in hand.