By default, the WordPress REST API can return considerably more data than the frontend needs: the full post content, excerpt, metadata, links, author information, and other internal fields. This is not always critical for a single post, but when loading a collection, unnecessary data quickly increases the JSON response size and the amount of work required on the server.
Optimization does not require changes to WordPress Core. In most cases, it is enough to construct requests correctly: limit the number of posts with per_page, select only the required fields with _fields, and avoid using _embed unless it is genuinely needed.
Why Unnecessary REST API Fields Create a Problem
A request to a standard endpoint such as /wp-json/wp/v2/posts returns a post object with many properties. For a news-list card, the frontend often needs only the ID, title, date, slug, and link. The full content or excerpt may not be used in this scenario, but it is still included in the response.
The more posts a single request returns, the larger the JSON becomes. The browser must download and parse this data, while PHP must prepare the response. The extra cost is especially noticeable on sites with long content, complex metadata, or a slow server.
This does not mean that every default response is critically slow. The problem occurs when a large amount of data is regularly sent for lists, searches, mobile clients, or headless WordPress projects.
- the response size and transfer time increase;
- the frontend processes data it does not use;
- the load on PHP and intermediate caches increases;
- mobile users consume more bandwidth.
Limit the Field Set with _fields
The _fields parameter lets you ask the REST API to return only the properties you need. This is the simplest step for optimizing standard endpoints. List fields separated by commas without spaces.
For example, a post list that requires only basic data can use the following request:
/wp-json/wp/v2/posts?per_page=10&_fields=id,slug,date,title,link
How to Select Fields in Nested Objects
Some REST API properties are objects. For example, title usually contains a separate rendered field. If the frontend needs only the title text, specify the nested field instead of the entire object:
- id — the post identifier;
- slug — the URL segment;
- date — the publication date;
- title.rendered — the displayed title;
- link — the ready-to-use post URL.
/wp-json/wp/v2/posts?per_page=10&_fields=id,slug,date,title.rendered,link
Do Not Select Fields Arbitrarily
Before shortening a response, check which properties the frontend actually uses. If you remove a required field, a component may stop displaying part of the data. After changing the request, test not only the HTTP response but also the behavior of cards, pagination, sorting, and links.
Also remember that _fields shortens the result for the client, but it does not turn the REST API into a completely custom SQL query. WordPress still prepares the response according to the endpoint's logic. Therefore, field filtering should be combined with a sensible number of items per request.
Use per_page and Short Pagination Pages
For collections, you should not load every post in a single request. The per_page parameter sets the number of items per page, while page specifies the page number. Smaller pages reduce the response size and allow the frontend to display content progressively.
A practical option for a list is to request 10 posts, or another number that the interface can actually display at once:
- set per_page according to the size of the list displayed on screen;
- send page to request subsequent batches of data;
- do not increase per_page merely to reduce the number of HTTP requests;
- handle cases where the requested page is beyond the available posts.
/wp-json/wp/v2/posts?per_page=10&page=2&_fields=id,slug,date,title.rendered,link
How to Determine the Number of Pages
WordPress collection responses usually include headers containing the total number of posts and pages. The frontend can use this information for a “Load more” button, traditional pagination, or infinite scrolling.
Do not rely only on the number of items in the current response: the final page may contain fewer posts than per_page. Check the response status and handle permission errors or invalid page numbers correctly.
Do Not Add _embed Unless It Is Necessary
The _embed parameter includes related resources in the response, such as the author, featured image, taxonomy terms, and other objects that WordPress can retrieve for a post. This is convenient when the frontend genuinely needs those details in a single request, but it can noticeably increase the response size for lists.
If a card displays only the title, date, and link, _embed is unnecessary. Adding it “just in case” often transfers nested objects that nobody uses.
- do not use _embed automatically in every request;
- add it only for scenarios that require related resources;
- when using _embed, also check whether the fields can be limited with _fields;
- compare the response size with and without _embed.
/wp-json/wp/v2/posts?per_page=10&_embed&_fields=id,slug,title.rendered,_embedded
When _embed Is Justified
The parameter may be appropriate for a news card that needs an image, the author's name, and a category at the same time. Its value should be assessed for the specific scenario: sometimes one request with embedded data is simpler and faster than several separate requests, while in other cases it creates excessive JSON.
For an accurate decision, compare actual responses in the browser's developer tools or from the command line. The important factors are not only kilobytes, but also response time, the number of requests, and the amount of data the frontend actually reads.
Build Minimal Responses for Custom Endpoints
If you create a custom REST endpoint, do not return the entire WP_Post object or an unprocessed query result. The client should receive a stable structure containing only the fields required for that particular scenario.
For example, a catalog endpoint might return an ID, name, price, short URL, and image, but not the full content, internal metadata, or every object relationship. This approach simplifies the contract between the backend and frontend and reduces the risk of accidentally exposing internal data.
- define a DTO-like response structure for each scenario;
- do not send internal meta fields unless they are required;
- normalize dates, URLs, and field names into a clear format;
- document required and optional properties.
register_rest_route('site/v1', '/cards', [
'methods' => 'GET',
'callback' => function ($request) {
$posts = get_posts([
'post_type' => 'post',
'posts_per_page' => 10,
'post_status' => 'publish',
]);
return array_map(function ($post) {
return [
'id' => $post->ID,
'slug' => $post->post_name,
'title' => get_the_title($post),
'link' => get_permalink($post),
];
}, $posts);
},
]);
Security for Custom Responses
Minimizing JSON does not replace permission checks. For private data or endpoints available only to authenticated users, configure permission_callback and capability checks separately. A field should not be considered safe merely because it is not displayed in the regular interface.
You should also avoid directly returning objects containing user metadata, tokens, internal integration IDs, or other service information.
How to Verify the Optimization Results
Optimization should be evaluated using real requests, not just by looking at the URL. Compare the standard and reduced responses for the same number of posts and confirm that the frontend receives all the data it needs.
Do not test only the successful scenario. Check an empty list, the final page, a missing image, a long title, network errors, and requests to an endpoint made without sufficient permissions.
- response size in the browser's Network panel;
- JSON wait time and download time;
- the number of items and pagination accuracy;
- the presence of every field read by JavaScript;
- caching behavior and repeated requests;
- PHP logs and REST API errors after the changes.
curl -i 'https://example.com/wp-json/wp/v2/posts?per_page=10&_fields=id,slug,date,title.rendered,link'
Common Mistakes
One common mistake is leaving _embed enabled for every request, even when it was needed only on a detail page. Another is setting per_page too high to “reduce” the number of requests. As a result, a single request becomes demanding for both the server and the browser.
You should also avoid adding _fields without checking nested structures. The request may formally return a 200 response, but the frontend may expect title.rendered and receive a different data shape or no required field at all.
Frequently asked questions
Should _fields always be used in the WordPress REST API?
For large collections and public requests, it is a recommended practice, especially when the frontend needs only part of an object. The benefit may be smaller for a one-off internal request, but the response structure should still be controlled.
Does _fields replace the _embed parameter?
No. _fields limits the fields in the response, while _embed adds related resources. They can be used together when the frontend needs embedded data, but you should check which properties are returned and whether the JSON has become too large.
What per_page value should you choose?
There is no universal value. Base your choice on the number of items the interface displays at once, the size of each post, and the server's capabilities. Several moderate-sized pages are usually better than one excessively large request.
Does _fields reduce PHP load?
It reliably reduces the data prepared for delivery to the client, but it does not always eliminate all of WordPress's internal work involved in preparing the object. For the greatest effect, combine _fields with pagination, avoiding unnecessary _embed usage, and using minimal custom responses.
Conclusion
An optimized WordPress REST request should return not “everything available,” but only the data required for a particular screen or feature. Start with three steps: limit per_page, list the required fields with _fields, and remove _embed wherever related resources are not needed.
For custom endpoints, build a minimal response structure and test it in the browser, with curl, and across real-world scenarios. This reduces JSON size, improves frontend performance, and helps avoid unnecessary PHP load without making risky changes to WordPress Core.