> ## Documentation Index
> Fetch the complete documentation index at: https://docs.convertly.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Client Hints for responsive images

> Let the browser send viewport width and DPR so Convertly picks the right CDN size without hard-coding w on every img.

[Client Hints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Client_hints) let the browser tell the CDN how wide an image is displayed and the device pixel ratio — so you can omit a fixed `w=` and still get correctly sized bytes. Convertly reads `Sec-CH-Width`, `Sec-CH-DPR`, and legacy `DPR` when you pass `ch=Width,Dpr` on the URL.

Reference: [Format & delivery → Client hints](/docs/image-cdn/transforms/format-delivery#client-hints).

<Note>
  Client Hints require **HTTPS** and a browser that sends the hints (Chrome, Edge, and Chromium-based browsers are the main adopters). Always provide a fallback width in `src` or a `w=` default for browsers that do not send hints.
</Note>

## When to use Client Hints vs srcset

| Approach                                                               | Best for                                                              |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------- |
| **`srcset` + `sizes`** ([responsive guide](/guides/responsive-images)) | Predictable layouts, `<ConvertlyImage>`, most React/Next apps         |
| **`ch=Width,Dpr`**                                                     | Fluid layouts, unknown slot widths — one URL adapts to viewport width |

You can combine both: fixed breakpoints in `<picture>` and Client Hints on individual hero images.

## Basic CDN URL

Omit `w` and opt in to hints:

```html theme={"system"}
<img
  src="https://cdn.convertly.sh/{endpointNamespace}/{fileId}?ch=Width,Dpr&fit=cover&h=600&format=auto"
  alt="Hero"
/>
```

Convertly multiplies `Sec-CH-Width` (CSS pixels) by `dpr` (from `Sec-CH-DPR` or the `dpr` query param) to derive output width, then applies `fit=cover` with your `h=600`.

See the before/after example in [Format & delivery](/docs/image-cdn/transforms/format-delivery).

## Enable hints in the browser

### Chrome (local testing)

1. Open `chrome://flags/#enable-experimental-web-platform-features` or ensure **Client Hints** are enabled for your origin.
2. Serve your page over **HTTPS** (or `localhost`).
3. Add a `<meta>` tag or `Accept-CH` response header so the browser knows which hints to send on the **next** navigation:

```html theme={"system"}
<meta http-equiv="Accept-CH" content="Width, DPR, Viewport-Width" />
```

Or from your origin (Next.js middleware, nginx, or your CDN's response headers):

```http theme={"system"}
Accept-CH: Width, DPR, Viewport-Width
```

### CDN image requests

Hints apply to the **document** that loads the `<img>`. The browser attaches `Sec-CH-*` headers to **subresource** requests (your Convertly CDN URLs) when the hint was negotiated for the top-level page.

## Next.js example

```tsx theme={"system"}
// middleware.ts — negotiate hints for all pages
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const response = NextResponse.next();
  response.headers.set("Accept-CH", "Width, DPR, Viewport-Width");
  return response;
}
```

```tsx theme={"system"}
import { createConvertlyCdn } from "@convertly-sh/image";

const cdn = createConvertlyCdn({ namespace: process.env.NEXT_PUBLIC_CONVERTLY_CDN_NAMESPACE! });

export function FluidHero({ fileId }: { fileId: string }) {
  return (
    <img
      src={cdn.url(fileId, { ch: "Width,Dpr", h: 600, fit: "cover" })}
      alt="Hero"
      style={{ width: "100%", height: "auto" }}
    />
  );
}
```

## Supported hint parameters

| URL param           | Header read             | Effect                                                      |
| ------------------- | ----------------------- | ----------------------------------------------------------- |
| `ch=Width`          | `Sec-CH-Width`          | Output width in CSS pixels (× DPR when Dpr is also enabled) |
| `ch=Dpr`            | `Sec-CH-DPR` or `DPR`   | Device pixel ratio multiplier                               |
| `ch=Width,Dpr`      | Both                    | Recommended combination                                     |
| `ch=Viewport-Width` | `Sec-CH-Viewport-Width` | Full viewport width when slot width is unknown              |

If no hint arrives, set an explicit fallback: `?w=1200&ch=Width,Dpr` uses `1200` when `Sec-CH-Width` is absent.

## Caching behaviour

Client Hint variants are cached separately. Convertly sets `Vary` appropriately so AVIF/WebP negotiation and hint-based widths do not collide at the edge. See [How caching works](/docs/image-cdn/transforms#how-caching-works).

## Related docs

* [Responsive images & art direction](/guides/responsive-images) — srcset, `<picture>`, `<ConvertlyImage>`
* [Format & delivery](/docs/image-cdn/transforms/format-delivery) — `format=auto`, Save-Data, metadata strip
* [CDN performance](/guides/cdn-performance) — cache keys and purge strategy
