WordPress REST API: Get Posts

The posts route /wp-json/wp/v2/posts is the one used most. This chapter shows how to list, filter and page through posts. Let us make some sample content first:

List posts

Terminal output

$ curl -s "http://example.com/wp-json/wp/v2/posts?_fields=id,date,title.rendered" | jq -c '.[]'
{"id":8,"date":"2026-03-04T10:00:00","title":{"rendered":"Site update"}}
{"id":7,"date":"2026-03-03T10:00:00","title":{"rendered":"Learn hooks"}}
{"id":6,"date":"2026-03-02T10:00:00","title":{"rendered":"Learn WP_Query"}}
{"id":5,"date":"2026-03-01T10:00:00","title":{"rendered":"WordPress 7 released"}}
{"id":1,"date":"2026-01-05T10:00:00","title":{"rendered":"Hello world!"}}

The newest post comes first, and only the published posts are shown (the draft is hidden, because we are not logged in). The default is 10 posts per page.

Common parameters

ParameterExampleWhat it does
per_pageper_page=2Number of items (1 to 100)
pagepage=2Page number
searchsearch=hooksSearch in the title and content
categoriescategories=3Filter by category ID (many IDs with comma)
tagstags=4Filter by tag ID
authorauthor=1Filter by author ID
orderby, orderorderby=title&order=ascSort the result
slugslug=site-updateGet posts by slug
after, beforeafter=2026-03-03T00:00:00Posts after or before a date
_fields_fields=id,titleReturn only these fields
_embed_embedAdd the linked data (author, categories, image) in the same response

Filter, search and sort

Terminal output

$ curl -s "http://example.com/wp-json/wp/v2/posts?categories=3&_fields=id,title.rendered" | jq -c '.[]'
{"id":7,"title":{"rendered":"Learn hooks"}}
{"id":6,"title":{"rendered":"Learn WP_Query"}}
$ curl -s "http://example.com/wp-json/wp/v2/posts?search=update&_fields=id,title.rendered" | jq -c '.[]'
{"id":8,"title":{"rendered":"Site update"}}
$ curl -s "http://example.com/wp-json/wp/v2/posts?orderby=title&order=asc&_fields=id,title.rendered" | jq -c '.[]'
{"id":1,"title":{"rendered":"Hello world!"}}
{"id":7,"title":{"rendered":"Learn hooks"}}
{"id":6,"title":{"rendered":"Learn WP_Query"}}
{"id":8,"title":{"rendered":"Site update"}}
{"id":5,"title":{"rendered":"WordPress 7 released"}}

Pagination

The headers tell the total number of items and pages, so a client can build the page links:

Terminal output

$ curl -s -I "http://example.com/wp-json/wp/v2/posts?per_page=2" | grep -i "^x-wp"
X-WP-Total: 5
X-WP-TotalPages: 3
$ curl -s "http://example.com/wp-json/wp/v2/posts?per_page=2&page=2&_fields=id,title.rendered" | jq -c '.[]'
{"id":6,"title":{"rendered":"Learn WP_Query"}}
{"id":5,"title":{"rendered":"WordPress 7 released"}}
$ curl -s "http://example.com/wp-json/wp/v2/posts?per_page=2&page=9" | jq -c '{code, message}'
{"code":"rest_post_invalid_page_number","message":"The page number requested is larger than the number of pages available."}

Asking for a page which does not exist gives an error with the code rest_post_invalid_page_number.

One post

Terminal output

$ curl -s "http://example.com/wp-json/wp/v2/posts/6?_fields=id,slug,link,categories,content.rendered" | jq -c .
{"id":6,"slug":"learn-wp_query","link":"http://example.com/learn-wp_query/","content":{"rendered":"<p>WP_Query gets posts from the database.</p>\n"},"categories":[3]}
$ curl -s "http://example.com/wp-json/wp/v2/posts/999" | jq -c '{code, message, status: .data.status}'
{"code":"rest_post_invalid_id","message":"Invalid post ID.","status":404}

Get the linked data with _embed

The author, categories and featured image are only IDs in the first response. Use _embed to get the full objects inside the key _embedded, so you need one request, not many:

Terminal output

$ curl -s "http://example.com/wp-json/wp/v2/posts/6?_embed" | jq -c '{title: .title.rendered, author: ._embedded.author[0].name, category: ._embedded["wp:term"][0][0].name}'
{"title":"Learn WP_Query","author":"admin","category":"Tutorials"}

Use it in JavaScript

fetch( '/wp-json/wp/v2/posts?per_page=3&_fields=id,title,link' )
	.then( ( response ) => response.json() )
	.then( ( posts ) => {
		posts.forEach( ( post ) => {
			console.log( post.title.rendered, post.link );
		} );
	} );
Note: The title.rendered and content.rendered values are HTML, not plain text. In a front end, escape or sanitize them before you put them on the page. Next: REST API Authentication.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.