How to Get Posts with REST API

If you’ve never worked with WordPress REST API before, then I am definitely recommend you to start with this tutorial, in which we are going to code some basic interactions with REST API using PHP and JavaScript. And as an example we’re just going to get posts from another WordPress blog.

First thing first we need to decide which blog’s posts we are going to get. I can not use my own blog for this example because I have REST API disabled :) I think we can use Matt Mullenweg’s blog for this example who is the founder of WordPress and whose blog has an open REST API (we can easily check it if we type in the browser: ma.tt/wp-json). So, the long story short WordPress REST API allows us to get posts from almost any WordPress blog and to display them either on another website or in a mobile app.

Let’s try to visit this URL then ma.tt/wp-json/wp/v2/posts. You can see that all the latest posts are displayed in your browser tab in JSON format.

WordPress API get posts in JSON format

And maybe the next question will be – what can we do with this JSON? Ok, right now I am about to show you two examples how to work with it with PHP and JavaScript functions.

Example 1. WordPress API – Get Posts in PHP

In our PHP example we can use cURL for sure but we can also use default WordPress HTTP API functions, in this case – wp_remote_get().

<?php
$response = wp_remote_get( 'https://ma.tt/wp-json/wp/v2/posts' );

if( 200 === wp_remote_retrieve_response_code( $response ) ) :

	$posts = json_decode( wp_remote_retrieve_body( $response ), true );
	foreach( $posts as $post ) :
		// you can print_r( $post ) or course
		?>
			<h2><?php echo $post[ 'title' ][ 'rendered' ] ?></h2>
			<p><?php echo $post[ 'excerpt' ][ 'rendered' ] ?></p>
		<?php
	endforeach;
	
endif;

Using transient cache

Most often when we work with any kind of API it is better to cache the API response with transients, it allows to significantly speed up the page loading.

<?php
// trying to get value from the cache
if( false === $posts = get_transient( 'misha_remote_cache' ) ) {
	$response = wp_remote_get( 'https://ma.tt/wp-json/wp/v2/posts' );

	if( 200 === wp_remote_retrieve_response_code( $response ) ) {
		$posts = json_decode( wp_remote_retrieve_body( $response ), true );
		set_transient( 'misha_remote_cache', $posts, HOUR_IN_SECONDS );
	}
}

if( $posts ) :
	foreach( $posts as $post ) :
		// you can print_r( $post ) or course
		?>
			<h2><?php echo $post[ 'title' ][ 'rendered' ] ?></h2>
			<p><?php echo $post[ 'excerpt' ][ 'rendered' ] ?></p>
		<?php
	endforeach;
endif;

Using parameters

If you check the official docs of REST API’s /wp/v2/posts endpoint you can find out that it supports plenty of parameters. For example if you’re wondering, why you get only 10 latest posts, then check out page and per_page parameters or if you would like to order posts alphabetically, then orderby and order parameters will come to help.

Let’s try it on an example:

$response = wp_remote_get(
	add_query_arg(
		array(
			'per_page' => 20,
			'page' => $current_page, // 1, 2, etc
			'orderby' => 'title',
			'order' => 'asc',
		),
		'https://ma.tt/wp-json/wp/v2/posts'
	)
);

if( 200 === wp_remote_retrieve_response_code( $response ) ) {
	...
}

By the way, it you want to get all posts with WordPress API, there are a couple of things to keep in mind:

  • Maximum possible value of per_page parameter is 100, if you provide 101 or higher, then you get an error. It means that if you have for example 200 posts to get, then you need to run two API requests with 'page' => 1 and 'page' => 2 while keeping the per_page value at 100.
  • Also a cURL timeout may occur, in order to resolve it, provide an additional timeout parameter to the wp_remote_get() function.
$response = wp_remote_get(
	add_query_arg(
		array( // posts from 101 to 200
			'per_page' => 100,
			'page' => 2,
		),
		'https://ma.tt/wp-json/wp/v2/posts'
	),
	array(
		'timeout' => 50, // Fix for: cURL error 28: Operation timed out after...
	)
);

Get custom post types

In order to have been able to get posts of a custom type with the WordPress REST API you just need to know what you should use as an API endpoint in your requests.

Post typeEndpoint
Posts post/wp/v2/posts
Pages page/wp/v2/pages
Custom post type custom_typeIn most cases you just need to use /wp/v2/custom_type but if during post type registration a custom rest_base parameter had been set, then you need to use it in the endpoint /wp/v2/rest_base

Get posts with statuses other than “publish”

Above I showed you a couple of examples where you can get posts from WordPress REST API without any authentication. And it works! But for sure when you try to get for example drafts or scheduled posts be ready to get an error “Invalid parameter(s): status” / “Status is forbidden.” instead and it seems quite logical to not allow absolutely anyone to get these kinds of posts.

But anyway let’s assume that you need to get all the scheduled posts, then you can do it that way:

$response = wp_remote_get(
	add_query_arg(
		array(
			'per_page' => 100,
			'status' => 'scheduled', 
			// publish (default), future, draft, pending, private, any
		),
		"{$url}/wp-json/wp/v2/posts"
	),
	array(
		'headers' => array(
			'Authorization' => 'Basic ' . base64_encode( "{$username}:{$pwd}" )
		)
	)
);

If you don’t know where to get $username and $pwd, read about application passwords.

Example 2. WordPress API – Get Posts in JavaScript

async function getWPPosts() {
	const response = await fetch( 'https://ma.tt/wp-json/wp/v2/posts' );
	const posts = await response.json();

	console.log( posts ); 

}

getWPPosts();

Below is what we have in the browser console after running the JavaScript code above:

WordPress API get posts JavaScript example
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X