{"id":13550037,"url":"https://github.com/igrigorik/http-client-hints","last_synced_at":"2025-04-07T10:28:55.376Z","repository":{"id":5829345,"uuid":"7044926","full_name":"igrigorik/http-client-hints","owner":"igrigorik","description":null,"archived":false,"fork":false,"pushed_at":"2016-02-04T01:37:14.000Z","size":3617,"stargazers_count":401,"open_issues_count":1,"forks_count":20,"subscribers_count":46,"default_branch":"master","last_synced_at":"2025-03-31T09:05:58.245Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igrigorik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-12-06T23:41:07.000Z","updated_at":"2024-10-30T10:50:30.000Z","dependencies_parsed_at":"2022-09-01T15:34:22.277Z","dependency_job_id":null,"html_url":"https://github.com/igrigorik/http-client-hints","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fhttp-client-hints","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fhttp-client-hints/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fhttp-client-hints/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fhttp-client-hints/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igrigorik","download_url":"https://codeload.github.com/igrigorik/http-client-hints/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247635064,"owners_count":20970662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T12:01:28.307Z","updated_at":"2025-04-07T10:28:55.346Z","avatar_url":"https://github.com/igrigorik.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"Development of this specification has moved to the HTTPWG repository. For latest drafts and issue discussions, head to:\n\n- https://github.com/httpwg/http-extensions#client-hints\n- https://httpwg.github.io/http-extensions/client-hints.html\n\n---\n\n## HTTP Client Hints Explainer\n\nThis specification defines a set of HTTP request header fields, colloquially known as Client Hints, that are intended to be used as input to proactive content negotiation; just as the `Accept` header allows clients to indicate what formats they prefer, Client Hints allow clients to indicate a list of device and agent specific preferences.\n\n\n* [Available hints](#available-hints)\n* [Opt-in hint delivery](#opt-in-hint-delivery)\n* [Use cases](#use-cases)\n  - [Responsive Design + Server Side Components (RESS)](#responsive-design--server-side-components-ress)\n  - [`\u003cimg\u003e` element](#img-element)\n    + [Delivering DPR-aware images](#delivering-dpr-aware-images)\n    + [Delivering DPR and resource width aware images](#delivering-dpr-and-resource-width-aware-images)\n  - [`\u003cpicture\u003e` element](#picture-element)\n    + [Device-pixel-ratio-based selection](#device-pixel-ratio-based-selection)\n    + [Device-pixel-ratio and viewport-based selection](#device-pixel-ratio-and-viewport-based-selection)\n    + [Resource selection](#resource-selection)\n  - [Maximum downlink speed](#maximum-downlink-speed)\n* [Hands-on example](#hands-on-example)\n* [Implementation status](#implementation-status)\n\n---\n\n### Available hints\nCurrent list includes `DPR` (device pixel ratio), `Width` (resource width), `Viewport-Width` (layout viewport width), and `Downlink` (maximum downlink speed) request headers, and `Content-DPR` response header that is used to confirm the DPR of selected image resources - see full definitions in \u003ca href=\"https://httpwg.github.io/http-extensions/client-hints.html\"\u003elatest spec\u003c/a\u003e.\n\n_Note: have a proposal for another hint? Open an issue, document your use case._\n\n### Opt-in hint delivery\nTo reduce request overhead the hints are sent based on opt-in basis: the server advertises supported hints, the user agent sends the appropriate hint request headers for subsequent requests - see \u003ca href=\"https://httpwg.github.io/http-extensions/client-hints.html#advertising-support-for-client-hints\"\u003eAdvertising Support for Client Hints\u003c/a\u003e.\n\nNote that this means that the user agent will not send hints on the very first request. However, if the site provides correct opt-in information in the response, hints will be delivered by all subsequent requests. Also, the user agent may remember site opt-in across browsing sessions, enabling hint delivery of all subsequent requests.\n\n\n### Use cases\n#### Responsive Design + Server Side Components (RESS)\n\nThe application may want to deliver alternate set of optimized resources based on advertised hints. For example, it may use the device pixel ratio (`DPR`), or the layout viewport width (`Viewport-Width`) to respond with optimized HTML markup, CSS, or script resources - see [Responsive Design + Server Side Components (RESS)](http://www.lukew.com/ff/entry.asp?1392).\n\n_Note: Applications that use this approach must also serve appropriate `Vary` and `Cache-Control` response headers to ensure correct delivery of optimized assets._\n\n#### `\u003cimg\u003e` element\n##### Delivering DPR-aware images\n`DPR` hint automates device-pixel-ratio-based selection and enables delivery of optimal image variant without any changes in markup. For example, given the following HTML markup:\n\n```html\n\u003cimg src=\"img.jpg\" alt=\"I'm a DPR-aware image!\"\u003e\n```\n\nThe client and server can negotiate the appropriate resolution of `img.jpg` via HTTP negotiation:\n\n```http\nGET /img.jpg HTTP/1.1\nUser-Agent: Awesome Browser\nAccept: image/webp, image/jpg\nDPR: 2.0\n```\n```http\nHTTP/1.1 200 OK\nServer: Awesome Server\nContent-Type: image/jpg\nContent-Length: 124523\nVary: DPR\nContent-DPR: 2.0\n\n(image data)\n```\n\nIn the above example, the user agent advertises its device pixel ratio via `DPR` request header on the image request. Given this information, the server is able to select and respond with the optimal resource variant for the client. For full details refer to the latest [spec](https://httpwg.github.io/http-extensions/client-hints.html).\n\n_Note: when server side DPR-selection is used the server must confirm the DPR of the selected resource via `Content-DPR` response header to allow the user agent to compute the correct intrinsic size of the image._\n\n##### Delivering DPR and resource width aware images\nIf the image resource width is known at request time, the user agent can communicate it to the server to enable selection of an optimized resource. For example, given the following HTML markup:\n\n```html\n\u003cimg src=\"img.jpg\" width=\"160\" alt=\"I'm a DPR and width aware image!\"\u003e\n```\n\nThe client and server can negotiate an optimized asset based on `DPR` and `Width` request hints:\n\n```http\nGET /img.jpg HTTP/1.1\nUser-Agent: Awesome Browser\nAccept: image/webp, image/jpg\nDPR: 2.0\nWidth: 320\n```\n```http\nHTTP/1.1 200 OK\nServer: Awesome Server\nContent-Type: image/jpg\nContent-Length: 124523\nVary: Width\nContent-DPR: 2.0\n\n(image data)\n```\n\nIn the above example, the user agent advertises its device pixel ratio and image resource width via respective `DPR` and `Width` headers on the image request. Given this information, the server is able to select and respond with the optimal resource variant for the client:\n\n* The server can scale the asset to requested width, or return the closest available match to help reduce number of transfered bytes.\n* The server can factor in the device pixel ratio of the device in its selection algorithm.\n\nNote that the width of the image may not be available at request time, in which case the user agent would omit the `Width` hint. Also, the exact logic as to which asset is selected is deferred to the server, which can optimize its selection based on available resources, cache hit rates, and other criteria.\n\n\n#### `\u003cpicture\u003e` element\n\nClient Hints can be used alongside [picture element](http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#the-picture-element) to automate resolution switching, simplify art-direction, and automate delivery of variable-sized images.\n\n##### Device-pixel-ratio-based selection\nDPR header automates [device-pixel-ratio-based selection](http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#introduction-3:device-pixel-ratio-2) by eliminating the need to write `x` descriptors for `img` and `picture` elements:\n\n```html\n\u003c!-- picture resolution switching --\u003e\n\u003cpicture\u003e\n  \u003csource srcset=\"pic1x.jpg 1x, pic2x.jpg 2x, pic4x.jpg 4x\"\u003e\n  \u003cimg alt=\"A rad wolf.\" src=\"pic1x.jpg\"\u003e\n\u003c/picture\u003e\n\n\u003c!-- alternative and equivalent syntax --\u003e\n\u003cimg src=\"pic1x.jpg\" srcset=\"pic2x.jpg 2x, pic4x.jpg 4x\" alt=\"A rad wolf.\"\u003e\n\n\u003c!-- equivalent functionality with DPR hint --\u003e\n\u003cimg alt=\"A rad wolf.\" src=\"pic.jpg\"\u003e\n\n\u003c!-- ... similarly ... --\u003e\n\n\u003c!-- picture art-direction with resolution switching --\u003e\n\u003cpicture\u003e\n  \u003csource media=\"(min-width: 45em)\" srcset=\"large-1.jpg, large-2.jpg 2x\"\u003e\n  \u003csource media=\"(min-width: 18em)\" srcset=\"med-1.jpg, med-2.jpg 2x\"\u003e\n  \u003cimg src=\"small-1.jpg\" srcset=\"small-2.jpg 2x\" alt=\"The president giving an award.\" width=\"500\" height=\"500\"\u003e\n\u003c/picture\u003e\n\n\u003c!-- equivalent functionality with resolution switching with Client Hints --\u003e\n\u003cpicture\u003e\n  \u003csource media=\"(min-width: 45em)\" srcset=\"large.jpg\"\u003e\n  \u003csource media=\"(min-width: 18em)\" srcset=\"med.jpg\"\u003e\n  \u003cimg src=\"small.jpg\" alt=\"The president giving an award.\" width=\"500\" height=\"500\"\u003e\n\u003c/picture\u003e\n```\n\nNote that the second example with [art direction-based selection](http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#introduction-3:art-direction-3) illustrates that hints do not eliminate the need for the `picture` element. Rather, Client Hints is able to simplify and automate certain parts of the negotiation, allowing the developer to focus on art direction, which by definition requires developer/designer input.\n\n##### Device-pixel-ratio and viewport-based selection\nThe combination of `DPR` and `Width` hints also simplifies delivery of variable sized images when [viewport-based selection](http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#introduction-3:viewport-based-selection-2) is used. The developer specifies the resource width of the image in `vw` units (which are relative to viewport width) via `sizes` attribute and the user agent handles the rest:\n\n```html\n\u003c!-- viewport-based selection --\u003e\n\u003cimg src=\"wolf-400.jpg\" sizes=\"100vw\" alt=\"The rad wolf\"\n     srcset=\"wolf-400.jpg 400w, wolf-800.jpg 800w, wolf-1600.jpg 1600w\"\u003e\n\n\u003c!-- equivalent functionality with DPR and Width hints --\u003e\n\u003cimg src=\"wolf.jpg\" sizes=\"100vw\" alt=\"The rad wolf\"\u003e\n```\n\n* Device pixel ratio is communicated via the `DPR` request header\n* The `vw` size is converted to physical `px` size based on client's layout viewport size and the resulting value is communicated via the `Width` request header\n* The server computes the optimal image variant based on communicated `DPR` and `Width` values and responds with the optimal image variant.\n\nHTTP negotiation flow for the example above:\n\n```\n\u003e GET /wolf.jpg HTTP/1.1\n\u003e DPR: 2.0\n\u003e Width: 800\n\n\u003c 200 OK\n\u003c Content-DPR: 2.0\n\u003c Vary: Width\n\u003c ...\n```\n\nIn situations where multiple layout breakpoints impact the image's dimensions the workflow is similar to that of the previous example:\n\n```html\n\u003c!-- multiple layout breakpoints --\u003e\n\u003cimg src=\"swing-400.jpg\" alt=\"Kettlebell Swing\"\n  sizes=\"(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)\"\n  srcset=\"swing-200.jpg 200w, swing-400.jpg 400w, swing-800.jpg 800w, swing-1600.jpg 1600w\"\u003e\n\n\u003c!-- equivalent functionality with DPR and Width hints --\u003e\n\u003cimg src=\"swing.jpg\" alt=\"Kettlebell Swing\"\n  sizes=\"(max-width: 30em) 100vw, (max-width: 50em) 50vw,calc (33vw - 100px)\"\u003e\n```\n\nThe combination of the `DPR` and `Width` hints allows the server to deliver 'pixel perfect' images that match the device resolution and exact display size. However, the server is not required to do so: it can round or bin the advertised values based on own logic and serve the closest matching resource - just as `srcset` picks the nearest resource based on the provided parameters in the markup.\n\n##### Resource selection\nWhen request hints are used the resource selection algorithm logic is shared between the user agent and the server: the user agent may apply own selection rules based on specified markup and defer other decisions to the server by communicating the appropriate `DPR` and `Width` values within the image request. With that, a few considerations to keep in mind:\n\n* The device pixel ratio and the resource width may change after the initial image request was sent to the server - e.g. layout change, desktop zoom, etc. When this occurs, and if resource selection is done via `sizes` or `srcset` attributes, the decision to initiate a new request is deferred to the user agent: it may send a new request advertising new hint values, or it may choose to reuse and rescale the existing asset. Note that this is the [default behavior of the user agent](https://github.com/ResponsiveImagesCG/picture-element/issues/230) - i.e. the user agent is **not** required to initiate a new request and use of hints does not modify this behavior.\n* For cases where an environment change (layout, zoom, etc.) must trigger a new asset download, you should use art-direction with `source` and appropriate media queries.\n\nUse of Client Hints does not incur additional or unnecessary requests. However, as an extra optimization, the server should [advertise the Key caching header](https://httpwg.github.io/http-extensions/client-hints.html#interaction-with-caches) to improve cache efficiency.\n\n\n#### Maximum downlink speed\nThe application may want to deliver an alternate set of resources (e.g. - alternate image asset, stylesheet, HTML document, media stream, and so on) based on the maximum downlink (`Downlink`) speed of the client, as defined by the [`downlinkMax` attribute](https://w3c.github.io/netinfo/#downlinkmax-attribute) in the W3C Network Information API.\n\n\n### Hands-on example\n\nA hands-on example courtesy of [resrc.it](http://www.resrc.it/):\n\n```bash\n# Request 100 CSS px wide asset with DPR of 1.0\n$\u003e curl -s http://app.resrc.it/http://www.resrc.it/img/demo/preferred.jpg \\\n  -o /dev/null -w \"Image bytes: %{size_download}\\n\" \\\n  -H \"DPR: 1.0\" -H \"Width: 100\"\nImage bytes: 9998\n\n# Request 100 CSS px wide asset with DPR of 1.5\n$\u003e curl -s http://app.resrc.it/http://www.resrc.it/img/demo/preferred.jpg \\\n  -o /dev/null -w \"Image bytes: %{size_download}\\n\" \\\n  -H \"DPR: 1.5\" -H \"Width: 150\"\nImage bytes: 17667\n\n# Request 200 CSS px wide asset with DPR of 1.0\n$\u003e curl -s http://app.resrc.it/http://www.resrc.it/img/demo/preferred.jpg \\\n  -o /dev/null -w \"Image bytes: %{size_download}\\n\" \\\n  -H \"DPR: 1.0\" -H \"Width: 200\"\nImage bytes: 28535\n```\n\nReSRC.it servers automate the delivery of optimal image assets based on advertised `DPR` and `Width` hint values and append the correct caching header (`Vary: DPR, Width`), which allows the asset to be cached on the client and by any Vary-capable intermediaries.\n\n\n### Implementation status\n* Blink: shipped in M46.\n  - [Automating resource selection with Client Hints](https://developers.google.com/web/updates/2015/09/automating-resource-selection-with-client-hints?hl=en) (Web Fundamentals).\n  - [Leaner Responsive Images With Client Hints](https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/) (Smashing Magazine).\n* IE: [Under Consideration](http://status.modern.ie/httpclienthints?term=client%20hints)\n* Mozilla: [935216 - Implement Client-Hints HTTP header](https://bugzilla.mozilla.org/show_bug.cgi?id=935216)\n\n\n### Feedback\nPlease feel free to open a new issue, or send a pull request!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrigorik%2Fhttp-client-hints","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figrigorik%2Fhttp-client-hints","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrigorik%2Fhttp-client-hints/lists"}