The Truth Behind Wpautop()

WordPress is great. We love it, build with it all the time. But gosh darn it, what is with the rogue “<p>” tags?  You’ll go through 92% of a site build, and then the widget you’re building on the last page of the site won’t quite line up properly. After an egregious round of ‘inspect element’ with Chrome’s developer tools, you’ll ask yourself in a half-eureka / half-chewing on your molars voice “where the f$@# is that p tag coming from? There’s no p tag!!”

So you’ll dig in to your post, and reassure yourself, yes, there is in fact no rogue p tag in your code. So, clearly WordPress has gone to the trouble to provide an unrequested p tag and its just cost you two hours you aren’t getting back unless I can finish my time machine (it’s on the list after the hover board, which it appears I have been beaten to).

After the coffe kicks in you remember, hey, you’re a developer, and there’s probably a code solution to this. And there is! Your day is made, or so you believe, by the following:

remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );

OMZ, thank Zeus for filters. So you install the filter, smile confidently and remember that you’re the (wo)man. Then tomorrow you right your next blog post, detailing your genius. Only when you go to Preview to stroke your ego on how much more the world is about to think of you, you discover that your post is one giant text block. What happened??!

What happened is that not only did WordPress remove those pesky mystery p tags from your buggy page, but all WordPress-inserted p tags from all your entire site! Yikes.

There must be a solution here, one that enables us to holster those p tags but crack those things like Billy the Kid when we need ‘em. Der is. It’s called scope. Normally this would occur to you. But then again, it’s 3:17am:

function my_wpautop() {
  if( is_page(11) || 5 && !is_single()) {
    remove_filter( 'the_content', 'wpautop' );
    remove_filter( 'the_excerpt', 'wpautop' );
add_action('pre_get_posts', 'my_wpautop');

The above code tells WordPress to remove auto-inserted p tags on two pages (with IDs 5 and 11), but not on any posts. Adjust your scope as necessary. Props to Andrzej Zglobica for pointing us in the right direction on this. Need more information? A detailed write-up on wpautop can be found here:

Follow us on Twitter: 


  • Caitlin Munley

    This is great, thank you for pointing me in the right direction. It didn’t work for me to use pre_get_posts (WordPress 3.7) but it did work to use the_post action. I wanted to only remove the automatic paragraphs from pages, so I did:

    function my_wpautop($post_obj) {
    if(is_page()) {
    remove_filter('the_content', 'wpautop');
    remove_filter('the_content', 'wptexturize');
    add_action('the_post', 'my_wpautop');

Next post: