# Get image dimensions from api before the acual images

**URL:** <https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372>\
**Category:** Technical Questions\
**Tags:** api, nextjs\
**Created:** [April 15, 2024, 4:37pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372 "2024-04-15T16:37:50Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![noahw](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@noahw](https://forum.builder.io/u/noahw)\
**Post date:** [April 15, 2024, 4:37pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/1 "2024-04-15T16:37:50Z")

</div>

**What I am trying to accomplish**  
I have a landing page, which has a mansory grid, that displays the images for the different sub-pages which are handled, via the builder visual cms. As this is a mansory grid and its important that all images acutally have their original size, I need to be able to make an api call to the cdn to really quickly retrieve the dimensions of the images so that i can render a placeholder of the images, before the load in. I know that i could just hardcode some dimensions for the pictures however this would result in a layout shift, after the images have loaded, because its not an ordinary grid, as mentioned above. If look all over the docs, but i could find a way to get this informations before hand so that i wont need to wait for the pictures to actually load in before I can display them correclty.

**Screenshots or video link**  
Screenshot how it would look like if the pictures are loaded, and i want to always have this layout beforehand, just with static colors so that everything is already the right size  
[https://imgur.com/a/oJb9Fmr](https://imgur.com/a/oJb9Fmr)

**Code stack you are integrating Builder with**  
I am using NextJs and the [Builder.io](http://Builder.io) SDK, however i dont need to do it via the SDK i could also just do it via a vanilla, rest api call. I am also using the package, `react-responsive-masonry` however i dont think this really matters.

---

<div class="post-metadata">

**Author:** ![manish-sharma](https://avatars.discourse-cdn.com/v4/letter/m/8797f3/32.png) [@manish-sharma](https://forum.builder.io/u/manish-sharma)\
**Post date:** [April 15, 2024, 4:59pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/2 "2024-04-15T16:59:44Z")

</div>

Hello @noahw,

Welcome to the [builder.io](http://builder.io) forum post.

You can use Builder’s Image API to access and download optimized versions of images that you’ve uploaded.

> **[Image API - Builder.io](https://www.builder.io/c/docs/image-api#query-parameter-reference)**
>
> Drag and drop with your components, right within your existing site or app. Build and optimize digital experiences for any tech stack, visually.

---

<div class="post-metadata">

**Author:** ![noahw](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@noahw](https://forum.builder.io/u/noahw)\
**Post date:** [April 15, 2024, 5:15pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/3 "2024-04-15T17:15:04Z")

</div>

yeah i know but, there i need to wait for the pictures to load first before i know their size, but I want to know them beforehand so that i can already preallocated the space needed for the picture, so that I have a placeholder for the image before it loads. Some images might take idk maybe half a second to load, to there will be a CLS because all the other static content is already loaded, so I want to avoid this by creatinh a placholder with the same dimensions as the image so that this will be displayed immediatly after the first contenful paint and afterwards if the images have loaded i can just substitute the placeholder for it.

---

<div class="post-metadata">

**Author:** ![manish-sharma](https://avatars.discourse-cdn.com/v4/letter/m/8797f3/32.png) [@manish-sharma](https://forum.builder.io/u/manish-sharma)\
**Post date:** [April 15, 2024, 5:44pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/4 "2024-04-15T17:44:03Z")

</div>

Hello @noahw,

Unfortunately, it’s not currently possible to retrieve the original size of an image without making an API call to the image API and then using JavaScript code to determine the actual width and height.

If you need dimensions, one approach is to create a data model that includes the image, width, height, and any other relevant information. This feature is already a requested enhancement, and you can upvote it here: [Image Original Size Feature Request](https://ideas.builder.io/ideas/PROD-I-348).

Thanks,

---

<div class="post-metadata">

**Author:** ![JonathanLand](https://avatars.discourse-cdn.com/v4/letter/j/c57346/32.png) [@JonathanLand](https://forum.builder.io/u/JonathanLand)\
**Post date:** [April 16, 2024, 12:51pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/5 "2024-04-16T12:51:35Z")

</div>

@noahw my solution to this problem was to find each page’s image URLs during the page build and running them through the `probe-image-size` package. Then I save the data to a React Context that wraps the `<BuilderComponent>` etc. This means that the data is only available for published pages, but that’s where it really matters.

---

<div class="post-metadata">

**Author:** ![noahw](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@noahw](https://forum.builder.io/u/noahw)\
**Post date:** [April 19, 2024, 7:24pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/6 "2024-04-19T19:24:59Z")

</div>

Oh yeah that sounds like a good solution, would you be able to maybe share the code, so that I could look at it because I have been trying to do this for a day now, but i can’t get it to work. I would really apperciate it if you would be so kind to just post the overall code structure to maybe a pastebin or to github. thanks in advance!

---

<div class="post-metadata">

**Author:** ![JonathanLand](https://avatars.discourse-cdn.com/v4/letter/j/c57346/32.png) [@JonathanLand](https://forum.builder.io/u/JonathanLand)\
**Post date:** [April 24, 2024, 7:52am UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/7 "2024-04-24T07:52:41Z")

</div>

The whole code structure is a bit complex because I do a whole bunch of other trickery this way during the build. I hope these few snippets can get you going (I’m omitting a few specifics, import statements, and type annotations etc.).

There are basically 4 files involved — the server-rendered `page.tsx` that calls the builder API and `extractData`; the client component that renders builder content inside the context provider; the context file (separated so it can be cleanly imported); and the `extractData` function itself.

```ts
// [[...path]]/page.tsx
builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!)

export default async function Page ({ params: { path } }) {
  const pageContent = await builder.get('page', {/* settings */})
  const extractedData = pageContent ? await extractData(pageContent) : {}
  /* ...more site-specific setup */

  return (  
    <RenderBuilderContent content={pageContent}
                          extractedData={extractedData}
                          model="page"
    />
  )
}

```

```ts
// RenderBuilderContent.ts
// in it's own file because the BuilderComponent needs 'use client'
'use client'

export function RenderBuilderContent ({ content, extractedData, model }) {
  /* ...more site-specific setup */
  
  return (
    <ExtractedDataContext.Provider value={extractedData}>
      <BuilderComponent
          content={content}
          model={model}
      />
    </ExtractedDataContext.Provider>
  )
}

```

```ts
// ExtractedDataContext.ts
import { createContext } from 'react'

export default createContext<Record<string, any>>({})

```

```ts
// extractData.ts

// get the value of a key from a JSON string
// this could theoretically also be achieved with a walker function, but since builder blocks have a well-known shape this is fine
const valueForKeyRegExp = (key: string) => new RegExp(`("${key}":\\s?")([^"]+)(")`, 'gm')

export default async function extractData (page) {
  const extractedData = {
    images: {},
    priorityAssets: [],
    /* other stuff we want to get */
  }

  async function getImageData ({ url }) {
    try {
      // pull in image data directly from the builder API endpoint
      const result = await require('probe-image-size')(url, { open_timeout: 30000, follow_max: 10 })
      // and store them using the URL as the key
      extractedData.images[url] = { ...result }
    } catch (e) {
      console.warn(e)
    }
  }

  const blocks = page?.data?.blocks
  for (const [i, block] of (blocks ?? []).entries()) {
    const text = JSON.stringify(block)
    for (const key of ['image', 'poster', /* ...any other keys used for images */]) {
      const matches = text.matchAll(valueForKeyRegExp(key))
      for (const match of matches) {
        const url = match[2]
        if (url) {
          await getImageData({ url })
          // get assets from the first 2 blocks and mark them for fetchpriority
          if (i <= 2) {
            extractedData.priorityAssets.push(url)
          }
        }
      }
    }
  }

  return extractedData
}

```

I’ve been thinking that I could also just append the `extractedData` to the API response itself (i.e. the `content` object) instead of using a Context, but haven’t gotten around to testing this.

Hope this helps!

---

<div class="post-metadata">

**Author:** ![noahw](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@noahw](https://forum.builder.io/u/noahw)\
**Post date:** [April 24, 2024, 3:50pm UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/8 "2024-04-24T15:50:08Z")

</div>

Thank you very much, this resolved my Problem and also gave me the opportunity to tweak my own RenderComponent even further if I need it in the future! Thank you again for your help!

---

<div class="post-metadata">

**Author:** ![JonathanLand](https://avatars.discourse-cdn.com/v4/letter/j/c57346/32.png) [@JonathanLand](https://forum.builder.io/u/JonathanLand)\
**Post date:** [April 25, 2024, 9:37am UTC](https://forum.builder.io/t/get-image-dimensions-from-api-before-the-acual-images/5372/9 "2024-04-25T09:37:12Z")

</div>

Glad I could help :​​)  
Feel free to update here if you come up with additional use cases for this. I’m curious what else we can come up with.

Also, here’s an example of the implementation, including the sizes and `priorityAssets` (I’m hoping more people find this post useful):

```ts
// myCustomImageComponent.tsx
export default myCustomImageComponent ({ imageUrl, alt }) {
  const extractedData = useContext(ExtractedDataContext) ?? {}
  const isPriorityAsset = extractedData.priorityAssets?.includes(imageUrl)

  return (
    <img src={imageUrl} 
         alt={alt}
         width={extractedData[imageUrl]?.width}
         height={extractedData[imageUrl]?.height}
         loading={isPriorityAsset ? undefined : 'lazy'}
         fetchPriority={isPriorityAsset ? 'high' : undefined}
    />
  )
}

```

Note that **optional chaining** is required, since new components in a page will not have these properties yet, until the page is published in Builder and rebuilt (that tripped me up a bit at first).
