Trying to change Content-Type: application/rss+xml to Content-Type: something/else on example.com/feed/.

My code so far:

function force_404() {
    global $wp_query;

    // Modify content-type header here, nothing I've tried works


add_action('do_feed', 'force_404', 1);
add_action('do_feed_rdf', 'force_404', 1);
add_action('do_feed_rss', 'force_404', 1);
add_action('do_feed_rss2', 'force_404', 1);
add_action('do_feed_atom', 'force_404', 1);

I initially thought the problem was the headers were already sent, but the 404 works, so that tells me they're still modifiable here. I'm at the end of my rope. Any help is appreciated.


My goal is to make the /feed/ 404 page render actual text/html in the browser instead of application/rss+xml, which renders as plain text. Changing the content-type header to text/html should do the trick.

Edit 2

It may not be possible to do this on /feed/, here is my evidence. I'm going to hold out hope that someone can confirm or deny.

  • Are you just trying to disable feeds? Mar 29 at 14:11
  • Nosir, trying to do something else entirely
    – Jeff
    Mar 29 at 14:15
  • 1
    what are you trying to do? Changing the http header is unlikely to be the solution you hoped, but that doesn't mean your task is impossible. Why are you trying to force the 404 page for feeds?
    – Tom J Nowell
    Mar 29 at 14:22
  • I want to make it so when the 404 page renders, it displays content-type: text/html instead of content-type: application/rss+xml. This will make the page render actual HTML instead of printing the HTML code.
    – Jeff
    Mar 29 at 14:27
  • @Jeff, that didn't really answer Tom's question, so once again, what are you really trying to do? What do you actually want to display at /feed? A WordPress 404 page? Why? Are you doing this just for /feed or feed/<anything> like /feed/atom? How would people subscribe to your site's feeds, because your code is essentially disabling feeds, except that you're disabling it by serving a 404 page? 🤔
    – Sally CJ
    Mar 30 at 7:03

2 Answers 2


If you just want to change the Content-Type header, then the feed_content_type filter can indeed be used for that purpose. (If your code isn't changing the header, then another code might have overridden that header, so you can try using a lower priority for your filter callback)

But there's another filter hook you can use, namely wp_headers. You can use it to change/remove the response headers set by WordPress on any pages.

So for example, for feed requests (/feed, /feed/atom, /comments/feed, etc.), WordPress sets the Content-Type, Last-Modified and ETag headers, hence you can change/remove any of that headers using the wp_headers filter.

However, as for what you're trying to do — display a WordPress's 404 page when the request is for a feed, a simpler way to do that is by using the parse_request action hook to change the request to a non-feed request and then set the error query var to 404 which then automatically intructs WordPress to show a 404 error page.

Working Example

add_action( 'parse_request', 'my_disable_feed_request' );
function my_disable_feed_request( $wp ) {
    // If it's a feed request, empty the `feed` query var and then make
    // WordPress shows a 404 error page by setting the `error` to 404.
    if ( ! empty( $wp->query_vars['feed'] ) ) {
        $wp->query_vars['feed']  = '';
        $wp->query_vars['error'] = '404';

So with that, you don't need to use the code in question, and actually, those do_feed hooks would no longer run because the feed request has been intercepted.

Note though, the above code will apply to any core WordPress feed URLs, so if you want the code to apply to the main feeds only, you can check if the request path starts with feed/ or that it's exactly feed, like so:

if ( ! empty( $wp->query_vars['feed'] ) && preg_match( '#^feed(/|$)#', $wp->request ) )
  • You are awesome. Being somewhat new to WP, I need to learn which variables to access (in a plugin context) and I'll be up and running in no time. Can you give me a nudge in the right direction to intercept requests for /wp-json.
    – Jeff
    Mar 31 at 9:05
  • You can basically use the parse_request hook (which is also used by WordPress core to handle /wp-json requests), however, I can only give a better or further insight after knowing what routes are you wanting to intercept and why so (because there could be a better solution than intercepting the request). So, perhaps you want to post a new question for that? But you should first check the REST API handbook because you might find something that can help you with whatever you're trying to do.
    – Sally CJ
    Mar 31 at 14:39

Your edit looks like you've got the filter concept reversed. Instead of apply_filters( 'feed_content_type', 'atom' );, try something like

add_filter( 'feed_content_type', 'wpse415005_change_feed_type', 10, 2 );
function wpse415005_change_feed_type( $content_type, $type ) {
     if ( 'rss' === $type || 'rss2' === $type ) {
          $content_type = 'something/else';
     return $content_type;


  • I appreciate that, Pat. I removed that edit so I don't muddy the waters. I put a more descriptive explanation in my comment above.
    – Jeff
    Mar 29 at 14:29
  • I'd recommend including that information in the question, too. That way, even if the comment thread grows long, your purpose will still be clear in the question itself.
    – Pat J
    Mar 29 at 14:32
  • @Jeff this filter (feed_content_type) is indeed the WordPress way of setting a different content type header at /feed. Have you actually tried this along with the code in your post? If yes and it didn't work, try reloading the page? (Or clear your caches)
    – Sally CJ
    Mar 29 at 16:40
  • Hi @SallyCJ, yes I did a hard reload bypassing the cache. Yes I actually tried it (many times, many variations). I think the problem is the feed/ content-type header is deeply hard-coded into WP. I'm sending the correct header, but WP is just not accepting it. Could also be the timing of sending my custom header, but I need a WP expert/dev to tell me.
    – Jeff
    Mar 29 at 17:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.