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.

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_pageparameter is100, if you provide101or 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' => 1and'page' => 2while keeping theper_pagevalue at100. - Also a cURL timeout may occur, in order to resolve it, provide an additional
timeoutparameter to thewp_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 type | Endpoint |
|---|---|
Posts post | /wp/v2/posts |
Pages page | /wp/v2/pages |
Custom post type custom_type | In 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:

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
Hi Misha,
Can we not just turn OFF REST API in WooCommerce settings?
You may ALSO want to add that we should disable WordPress REST API as well in order to make our data completely secure!
Thanks.
Hi,
Sorry for delay in replying – do you mean to disable REST API for WordPress without disabling WooCommerce API?
No, I meant in order to gain complete security, we should disable BOTH WooCommerce API as well as WordPress REST API.
Since I am also learning about WordPress / Woocommerce, please share your knowledge on achieving this.
Thanks.
But this code from the post disables both WooCommerce and WordPress REST API, so just try to access this Woo API endpoint
/wp-json/wc/v2/orders.Thanks Misha, perhaps I did not check properly. I also was checking for
/wc-api/v3Hello dear,
Thank you for your great article, i enjoy it so much, it is easy to read,
so right now, i want to know from you, how to use client API key in wordpress site,
i mean that where to start working 1st.? you have written “Latest Posts from Matt Mullenweg’s Blog”
below codes, that was really great, but i’m confuse that, which file i should write this codes? please ans to me ASAP i’m waiting for your great response, as i’m a beginner, my client is wanting some categories posts can show his site,
Thank you so much,
Hello,
No API key is required in this case, you just have to specify a correct endpoint URL. You can insert this code in the place where you would like to show the posts.
Thanks Misha,
I tested your code and when I try to get posts from my website, I get a 403 error.
But if I check that same URL from the browser, I get 200 response… How come? what am I missing?
seems like ModSecurity was the issue… Thanks anyway :)
Thank you – very well done!