StrapiREST APINode.jsHeadless CMS

Strapi 5 Populate Guide: Relations, Media, and Nested Queries

Use Strapi 5 REST populate correctly for relations, media, components, nested queries, field selection, qs query builders, and safer production response sizes.

·Updated ·11 min read·Counting...
Strapi 5 Populate Guide: Relations, Media, and Nested Queries

Strapi REST API does not automatically return relations, media, components, and dynamic zones. You must declare what to populate. populate=* is useful for local exploration, but production pages should request precise fields and relations.

This guide focuses on Strapi 5. Strapi 4 response shapes and some behaviors differ, so confirm your project version before copying code.

Example content model

Assume Article has:

  • title, slug, and excerpt
  • cover media
  • author relation
  • category relation
  • comments relation
  • seo component

A plain request:

GET /api/articles

returns article fields, but does not recursively expand all relations. This prevents accidental loading of the whole content graph.

populate=*

GET /api/articles?populate=*

This is fine for debugging or simple previews. It does not mean "load infinite depth." As the content model grows, wildcard population can make responses much larger and slower.

Populate only what you need

For cover and author:

GET /api/articles?populate[cover]=true&populate[author]=true

Limit main fields too:

GET /api/articles?fields[0]=title&fields[1]=slug&fields[2]=excerpt&populate[cover]=true&populate[author]=true

Use fields for ordinary fields. Use populate for relations, media, components, and dynamic zones.

Select fields inside populated data

If the author only needs a name and the cover only needs URL and alt text:

GET /api/articles?populate[author][fields][0]=name&populate[cover][fields][0]=url&populate[cover][fields][1]=alternativeText

Field selection reduces response size and accidental exposure. It is not a replacement for permissions. Real access control belongs in roles, API tokens, policies, and controllers.

Nested populate

For comments and each comment's author:

GET /api/articles?populate[comments][populate][author][fields][0]=name

You can also select and sort comment fields:

GET /api/articles?populate[comments][fields][0]=content&populate[comments][sort][0]=createdAt:desc&populate[comments][populate][author][fields][0]=name

Nested queries can become expensive quickly. If a page only shows a comment count, do not load all comments and authors just to compute that number.

Use qs for complex queries

Bracket URLs are easy to mistype. Use qs:

import qs from "qs"

const query = qs.stringify(
  {
    fields: ["title", "slug", "excerpt"],
    populate: {
      cover: { fields: ["url", "alternativeText"] },
      author: { fields: ["name"] },
      comments: {
        fields: ["content", "createdAt"],
        sort: ["createdAt:desc"],
        populate: {
          author: { fields: ["name"] },
        },
      },
    },
  },
  { encodeValuesOnly: true },
)

const response = await fetch(`${STRAPI_URL}/api/articles?${query}`)

Keep query objects in a data access layer, not copied across many React components.

Next.js fetch wrapper

type Article = {
  documentId: string
  title: string
  slug: string
  excerpt: string
  cover?: { url: string; alternativeText?: string }
  author?: { name: string }
}

export async function getArticles(): Promise<Article[]> {
  const response = await fetch(`${process.env.STRAPI_URL}/api/articles?${query}`, {
    next: { revalidate: 300 },
  })

  if (!response.ok) {
    throw new Error(`Strapi request failed: ${response.status}`)
  }

  const payload = await response.json()
  return payload.data
}

If code still reads data.attributes, verify whether it was written for Strapi 4.

Common problems

If populate returns empty data, check:

  1. Related content is published.
  2. Public role or API token has read permission for the target type.
  3. Field names match the Content-Type Builder.
  4. Locale, publication state, or filters are not excluding the content.
  5. Front-end code reads the Strapi 5 response shape correctly.

If responses are too slow or too large:

  • Replace populate=* with explicit fields.
  • Avoid loading body, comments, and authors on list pages.
  • Add pagination.
  • Split complex pages into separate queries.
  • Consider page-specific custom controllers.

Subscribe to FreeMac

Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.