No image in the API response

System Information
  • Strapi Version: 4.0.0
  • Operating System: WIN 10
  • Database: no database
  • Node Version: 14.17.5
  • NPM Version: 8.1.4
  • Yarn Version:

Hello, I’ve set up a new strapi project to create a blog with Next.js version 12.0.5.

There was no problem when I created a “Post” collection and some fields(content, title, etc …).
I can easily call “http://localhost:1337/api/posts”, and I will receive my fields and my data.

But I want a thumbnail image with my Posts, so I’ve basically created an “image” field on my “Post” collection.
And from then, I just can’t receive my image as a property in my API response.
There is the whole object, with every prop (content, title, etc…), but the image is nowhere to be found.

I’ve double checked my permissions on the public role and it’s all checked.
My image is uploaded, I can see it in the “media library” and I can also retrieve it with a link “/uploads/myimage”.

But I don’t want to get it via that link, I want it with with my “posts” request indeed.

Is there something I did wrong ? Is there a special thing to do to be able to request the images ?

Thanks a lot if someone if passing by, I’ve struggled way too long with that.
Have a nice day.

Hi, just extend your request with the ?populate=* parameters. In your case the request should be: http://localhost:1337/api/posts?populate=* You can read more about this topic in the docs.


Awesome, it’s working ! Thanks a lot.

I need a little explanation though, why all my fields are shown by default(text, boolean, date, etc …) but not the image field ?

Why do I need to specify the populate=* to get it ?

I saw this in the docs “By default, relations are not populated when fetching entries.”

But “image” is a field, not a relation ?
A relation is when we bound two categories together right (like Post and Category)?

As far as I know the reasons behind this behaviour were performance considerations. As you can see that an image response contains a lot attributes, most likely more than you have with all of other fields together. The same goes to the other kind of realtions.

With this behaviour you can opt in the performance heavy response types only if you really need it.

1 Like

I tried doing the same. ?populate=* doesn’t seem to fetch the url of the image. It gets all the fields except for the image field.


Had the same problem–not sure why the * doesn’t get it, but I found that chaining the * populate query with a specific field populate query works.

In my case, I have a business logo inside a component. The “business_information” component had several other fields that were showing, but the logo was omitted. To get it, I made this call:


It’s a bit weird, but * apparently doesn’t mean all all :smiley:

Wait, the answer above is WRONG! I added a “location” component as well and then discovered that the wildcard * wasn’t working in conjunction with the specific business_information.logo populate parameter. business_information was populating in full, including media, and the top-level information not in components was also coming through, but no location. So, basically, it seems you can’t actually chain the wildcard with more specific populate requests.

So after digging through docs a bit more I settled on simply chaining specific populate parameters. So, instead of wildcard + specific, I’m now just specifically calling components and the data I need inside them.

That brought me to this:


However, location has relations with a city and a neighborhood collection, and that’s not populating with just this call.

So now, what’s working for me is this–there might be a better way, but this is the first thing that worked for me:


This is getting a bit out of hand in terms of query params, though, so I decided to make a custom controller for returning the fields I want with just a call to populate=*.

This thread has helpful information on custom controllers for full population.

These docs are also helpful.

Ultimately, I landed on this:

"use strict";

 *  venue controller

const { createCoreController } = require("@strapi/strapi").factories;

// module.exports = createCoreController('api::venue.venue');

const uid = "api::venue.venue";

module.exports = createCoreController(uid, () => {
  const components = {
    location: {
      populate: {
        city: true,
        neighborhood: true,
    business_information: {
      populate: {
        logo: true,

  return {
    async find(ctx) {
      // overwrite default populate=* functionality
      if (ctx.query.populate === "*") {
        const entity = await strapi.entityService.findMany(uid, {
          populate: components,
        const sanitizedEntity = await this.sanitizeOutput(entity, ctx);

        return this.transformResponse(sanitizedEntity);
      // maintain default functionality for all other request
      return super.find(ctx);
    async findOne(ctx) {
      const { id } = ctx.request.params;

      if (ctx.query.populate === "*") {
        const entity = await strapi.entityService.findOne(uid, id, {
          populate: components,
        const sanitizedEntity = await this.sanitizeOutput(entity, ctx);

        return this.transformResponse(sanitizedEntity);

      return super.findOne(ctx);

After reading through some GitHub issues, there are apparently some additional wildcard selectors in the works that will populate all components/relations by default to certain depths, but this is working in the meantime!

Hopefully I don’t need another correction on this :smiley:

Instead of populate= * use media


I have exactly the same issue. The image component I have created shows all the data other than the media. Has anyone got a solution for this?

(populate=* does not solve this issue for me)

i have just faced this issue myself and found this package. Populate deep | Strapi Market which does exactly what you need.

1 Like

Hey, that looks fantastic! Thanks for sharing–I’ll give it a shot.

thank you this plugin work for me.