When building WordPress themes or plugins, sanitizing user input is essential for security. But sometimes, you need to sanitize content without stripping all the HTML, especially if you’re allowing trusted users (like admins or editors) to format content using safe HTML tags like <strong>
, <a>
, or <code>
.

In this tutorial, you’ll learn how to sanitize WordPress content while preserving safe HTML, using built-in WordPress functions.
🔐 Why You Need to Sanitize (But Keep HTML)
- Prevent XSS (Cross-site Scripting) attacks
- Allow users to format posts, bios, or inputs safely
- Avoid breaking content by stripping valid tags
WordPress provides several sanitization and escaping functions—some remove all HTML (like sanitize_text_field()
), while others let you define which tags are safe.
✅ Recommended Function wp_kses()
This is the key function for keeping safe HTML and removing anything dangerous.
$allowed_tags = array(
'a' => array(
'href' => true,
'title' => true,
'target' => true,
'rel' => true
),
'strong' => array(),
'em' => array(),
'code' => array(),
'pre' => array(),
'br' => array(),
'p' => array(),
'ul' => array(),
'ol' => array(),
'li' => array()
);
$clean_content = wp_kses( $user_input, $allowed_tags );
🧼 What it does:
- Keeps only the tags you allow (like
<a>
,<strong>
, etc.) - Strips out scripts, inline styles, or unwanted attributes
🛡️ Bonus: Use wp_kses_post()
for WordPress Editor-Like Safety
WordPress also provides a helper function that mimics the default HTML allowed in the block editor or classic editor:
$clean_content = wp_kses_post( $user_input );
This is great for:
- Sanitizing post content
- User-submitted comments or bios (trusted roles)
- Custom post meta that supports formatting
✍️ Use Case Example: Sanitizing a Custom Field with HTML
Let’s say you have a user-submitted bio field in a user profile form:
if ( isset( $_POST['bio'] ) ) {
$sanitized_bio = wp_kses_post( $_POST['bio'] );
update_user_meta( $user_id, 'bio', $sanitized_bio );
}
This lets users include basic formatting like <strong>
or <a>
but prevents script injection or unsafe HTML.
❌ What Not To Use (If You Want to Keep HTML)
sanitize_text_field()
→ Strips all HTMLesc_html()
→ Converts<
and>
to entities (no HTML output)strip_tags()
→ Removes everything inside angle brackets
Use these only when you want plain text output.
✅ Quick Summary
Function | Keeps HTML? | Best Use |
---|---|---|
sanitize_text_field() | ❌ No | Plain text inputs |
wp_kses() | ✅ Yes (custom tags) | Fine-tuned sanitizing |
wp_kses_post() | ✅ Yes (WordPress default tags) | User-generated post content |
esc_html() | ❌ No | Display only, escape for output |
strip_tags() | ❌ No | Hard strip of all tags |
🎯 Final Thoughts
When dealing with user input in WordPress, security should always come first—but that doesn’t mean you have to sacrifice flexibility. With functions like wp_kses()
and wp_kses_post()
, you can sanitize safely while still allowing meaningful HTML formatting.
This is perfect for custom fields, user bios, comments, or any feature that enhances your UX through rich text.