When using the WordPress REST API within a JavaScript application, you might encounter an error like this:

Access to XMLHttpRequest at 'https://wordpress.dev/wp-json/wp/v2/posts' from origin 'http://localapp.test' has been blocked by CORS policy: Request header field x-requested-with is not allowed by Access-Control-Allow-Headers in preflight response.

Most CORS issues can be solved by adding the following to your .htaccess file:

Header add Access-Control-Allow-Origin "*"

However, when you try the REST API request again from your application, you’ll get a new error.

'Access-Control-Allow-Origin' header contains multiple values 'http://localapp.test, *', but only one is allowed

But why? The .htaccess rule we added from above only has a single value. The reason for this is that the WordPress REST API is already setting CORS headers using the rest_send_cors_headers() function. You can override this by removing the existing CORS headers provided by WordPress and defining your own.

Add the following to your functions.php file:

function my_custom_rest_cors() {
  remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
  add_filter( 'rest_pre_serve_request', function( $value ) {
    header( 'Access-Control-Allow-Origin: *' );
    header( 'Access-Control-Allow-Methods: GET' );
    header( 'Access-Control-Allow-Credentials: true' );
    header( 'Access-Control-Expose-Headers: Link', false );

    return $value;
  } );
add_action( 'rest_api_init', 'my_custom_rest_cors', 15 );

There are lots of reasons why you wouldn’t setup the headers in the way shown above, but this is a great baseline for getting the REST API configured to play nice with Axios, jQuery.ajax() or the Fetch API.

Hope that helps!

Did You Find This Helpful?

Join my biweekly digest of curated HTML, CSS and JavaScript news.

Matt Litzinger headshot

Matt Litzinger

Matt is a New Hampshire-based web developer focused on UX and digital accessibility.