Proxy servers and tunneling - HTTP

Proxy servers and tunneling
===========================

When navigating through different networks of the Internet, proxy servers and HTTP tunnels are facilitating access to content on the World Wide Web. A proxy can be on the user's local computer, or anywhere between the user's computer and a destination server on the Internet. This page outlines some basics about proxies and introduces a few configuration options.

There are two types of proxies: **forward proxies** (or tunnel, or gateway) and **reverse proxies** (used to control and protect access to a server for load-balancing, authentication, decryption or caching).

Forward proxies
---------------

A forward proxy, or gateway, or just "proxy" provides proxy services to a client or a group of clients. There are likely hundreds of thousands of open forward proxies on the Internet. They store and forward Internet services (like the DNS, or web pages) to reduce and control the bandwidth used by the group.

Forward proxies can also be anonymous and allow users to hide their IP address while browsing the Web or using other Internet services. For example, Tor routes internet traffic through multiple proxies for anonymity.

Reverse proxies
---------------

As the name implies, a reverse proxy does the opposite of what a forward proxy does: A forward proxy acts on behalf of clients (or requesting hosts). Forward proxies can hide the identities of clients whereas reverse proxies can hide the identities of servers. Reverse proxies have several use cases, a few are:

* Load balancing: distribute the load to several web servers,
* Cache static content: offload the web servers by caching static content like pictures,
* Compression: compress and optimize content to speed up load time.
Forwarding client information through proxies
---------------------------------------------

Proxies can make requests appear as if they originated from the proxy's IP address. This can be useful if a proxy is used to provide client anonymity, but in other cases information from the original request is lost. The IP address of the original client is often used for debugging, statistics, or generating location-dependent content. A common way to disclose this information is by using the following HTTP headers:

The standardized header:

`Forwarded`

Contains information from the client-facing side of proxy servers that is altered or lost when a proxy is involved in the path of the request.

Or the de-facto standard versions:

`X-Forwarded-For`
Non-standard

Identifies the originating IP addresses of a client connecting to a web server through an HTTP proxy or a load balancer.

`X-Forwarded-Host`
Non-standard

Identifies the original host requested that a client used to connect to your proxy or load balancer.

`X-Forwarded-Proto`
Non-standard

identifies the protocol (HTTP or HTTPS) that a client used to connect to your proxy or load balancer.

To provide information about the proxy itself (not about the client connecting to it), the `Via` header can be used.

`Via`

Added by proxies, both forward and reverse proxies, and can appear in the request headers and the response headers.

HTTP tunneling
--------------

Tunneling transmits private network data and protocol information through public network by encapsulating the data. HTTP tunneling is using a protocol of higher level (HTTP) to transport a lower level protocol (TCP).

The HTTP protocol specifies a request method called `CONNECT`. It starts two-way communications with the requested resource and can be used to open a tunnel. This is how a client behind an HTTP proxy can access websites using TLS (i.e. HTTPS, port 443). Note, however, that not all proxy servers support the `CONNECT` method or limit it to port 443 only.

See also the HTTP tunnel article on Wikipedia.

Proxy Auto-Configuration (PAC)
------------------------------

A Proxy Auto-Configuration (PAC) file is a JavaScript function that determines whether web browser requests (HTTP, HTTPS, and FTP) go directly to the destination or are forwarded to a web proxy server. The JavaScript function contained in the PAC file defines the function:

The auto-config file should be saved to a file with a `.pac` filename extension: `proxy.pac`.

And the MIME type set to `application/x-ns-proxy-autoconfig`.

The file consists of a function called `FindProxyForURL`. The example below will work in an environment where the internal DNS server is set up so that it can only resolve internal host names, and the goal is to use a proxy only for hosts that aren't resolvable:

```js
function FindProxyForURL(url, host) {
  if (isResolvable(host)) {
    return "DIRECT";
  }
  return "PROXY proxy.mydomain.com:8080";
}
```

See Proxy Auto-Configuration (PAC) for more examples.

See also
--------

* `CONNECT`
* Proxy server on Wikipedia


Permissions Policy - HTTP

Permissions Policy
==================

**Permissions Policy** provides mechanisms for web developers to explicitly declare what functionality can and cannot be used on a website. You define a set of "policies" that restrict what APIs the site's code can access or modify the browser's default behavior for certain features. This allows you to enforce best practices, even as the codebase evolves — as well as more safely compose third-party content.

Permissions Policy is similar to Content Security Policy but controls features instead of security behavior.

Examples of what you can do with Permissions Policy:

* Change the default behavior of autoplay on mobile and third-party videos.
* Restrict a site from using sensitive devices like the camera, microphone, or speakers.
* Allow iframes to use the Fullscreen API.
* Stop items from being scripted if they are not visible in the viewport, to improve performance.

**Note:** Permissions Policy used to be called Feature Policy. The name has changed, and so has the HTTP header syntax, so bear this in mind if you have used Feature Policy in the past, and check the browser support tables. The `<iframe allow=" ... ">` syntax has stayed the same.

Concepts and usage
------------------

The web provides functionality and APIs that may have privacy or security risks if abused. In such cases, you may wish to strictly limit how functionality is used on a website. In each case, there should be an intuitive or non-breaking way for web developers to detect and handle cases where a feature is disabled.

Some approaches include:

* "Permission denied" is returned for JavaScript APIs that require user permission grants.
* JavaScript APIs that provide access to features return `false` values or throw an error.
* APIs are not even exposed, as though they don't exist.
* Options that control the feature behavior have different default values.

**Note:** Newly-introduced features may have an explicit API to signal the state. Existing features that later integrate with Permissions Policy will typically use existing mechanisms.

Permissions Policy allows you to control which origins can use which features, both on the top-level page and in embedded `<iframe>`s. The aim is to enforce best practices for good user experiences and provide granular control over *sensitive* or *powerful* features (meaning features that a user is required to give express permission for usage of, before related code can be executed).

Permissions Policy provides two ways to specify policies:

* The `Permissions-Policy` HTTP header, to control feature usage in received responses and any embedded content within the page (which includes `<iframe>`s).
* The `<iframe>` `allow` attribute, to control feature usage only in specific `<iframe>`s.

These are separate but related — see Inheritance of policies for embedded content for details.

**Note:** Scripts can programmatically query information about the permission policy via the `FeaturePolicy` object located at either `Document.featurePolicy` or `HTMLIFrameElement.featurePolicy`.

To control each feature, you write a policy that consists of:

* A **directive** that identifies the name of the feature to control. See the list of the different available directives.
* An **allowlist**, which is a list of origins that the feature should be controlled in. You can enable a feature for all or specific origins, or block its usage in all origins.

See below for multiple examples.

Relationship with the Permissions API
-------------------------------------

Permissions Policy and the Permissions API are closely-related, but different. The features that have their permissions controlled by both these technologies overlap.

* Permissions Policy allows a server to set whether a feature can be used in a particular document (or embedded `<frame>`s within it). These are referred to as **policy-controlled** features — see the list of Permissions Policy directives.
* The Permissions API gates access to features based on user-granted permissions. These features are recorded in the Permissions Registry.

The identifying string used for each feature is kept consistent across both, for example, `geolocation` for the Geolocation API. Most of the API features in the Permissions Registry also have a corresponding Permissions Policy directive. One exception is the Notifications API.

Generally when a Permissions Policy blocks the use of a powerful feature, the user won't even be asked for permission to use it, and the Permissions API `query()` method will return a `state` value of `denied`.

See also Permissions > Relationship to the Permissions Policy specification.

Allowlists
----------

An allowlist is a list of origins that takes one or more of the following values contained in parentheses, separated by spaces:

* `*`: The feature will be allowed in this document, and all nested browsing contexts (`<iframe>`s) regardless of their origin.
* `()` (empty allowlist): The feature is disabled in top-level and nested browsing contexts. The equivalent for `<iframe>` `allow` attributes is `'none'`.
* `self`: The feature will be allowed in this document, and in all nested browsing contexts (`<iframe>`s) in the same origin only. The feature is not allowed in cross-origin documents in nested browsing contexts. `self` can be considered shorthand for `https://your-site.example.com`. The equivalent for `<iframe>` `allow` attributes is `self`.
* `src`: The feature will be allowed in this `<iframe>`, as long as the document loaded into it comes from the same origin as the URL in its src attribute. This value is only used in the `<iframe>` `allow` attribute, and is the *default* `allowlist` value in `<iframe>`s.
* `"<origin>"`: The feature is allowed for specific origins (for example, `"https://a.example.com"`). Origins should be separated by spaces. Note that origins in `<iframe>` allow attributes are not quoted.

The values `*` and `()` may only be used on their own, while `self` and `src` may be used in combination with one or more origins.

**Note:** Directives have a default allowlist, which is always one of `*`, `self`, or `none` for the `Permissions-Policy` HTTP header, and governs the default behavior if they are not explicitly listed in a policy. These are specified on the individual directive reference pages. For `<iframe>` `allow` attributes , the default behavior is always `src`.

Where supported, you can include wildcards in Permissions Policy origins. This means that instead of having to explicitly specify several different subdomains in an allowlist, you can specify them all in a single origin with a wildcard.

So instead of

```http
("https://example.com" "https://a.example.com" "https://b.example.com" "https://c.example.com")
```

You can specify

```http
("https://example.com" "https://*.example.com")
```

**Note:** `"https://*.example.com"` does not match `"https://example.com"`.

allowlist examples:

* `*`
* `()`
* `(self)`
* `(src)`
* `("https://a.example.com")`
* `("https://a.example.com" "https://b.example.com")`
* `(self "https://a.example.com" "https://b.example.com")`
* `(src "https://a.example.com" "https://b.example.com")`
* `("https://*.example.com")`
Permissions-Policy header syntax
--------------------------------

The general syntax looks like this:

```http
Permissions-Policy: <directive>=<allowlist>
```

So for example to block all access to geolocation, you would do this:

```http
Permissions-Policy: geolocation=()
```

Or to allow access to a subset of origins, you'd do this:

```http
Permissions-Policy: geolocation=(self "https://a.example.com" "https://b.example.com")
```

Several features can be controlled at the same time by sending the header with a comma-separated list of policies, or by sending a separate header for each policy.

For example, the following are equivalent:

```http
Permissions-Policy: picture-in-picture=(), geolocation=(self https://example.com), camera=\*;

Permissions-Policy: picture-in-picture=()
Permissions-Policy: geolocation=(self https://example.com)
Permissions-Policy: camera=\*
```

Iframe syntax
-------------

For an `<iframe>` to have a feature enabled its allowed origin must also be in the allowlist for the parent page. Because of this inheritance behavior, it is a good idea to specify the widest acceptable support for a feature in the HTTP header, and then specify the subset of support you need in each `<iframe>`.

The general syntax looks like this:

```html
<iframe src="<origin>" allow="<directive> <allowlist>"></iframe>
```

So for example to block all access to geolocation, you would do this:

```html
<iframe src="https://example.com" allow="geolocation 'none'"></iframe>
```

To apply a policy to the current origin and others, you'd do this:

```html
<iframe
 src="https://example.com"
 allow="geolocation 'self' https://a.example.com https://b.example.com"></iframe>
```

This is important: By default, if an `<iframe>` navigates to another origin, the policy is not applied to the origin that the `<iframe>` navigates to. By listing the origin that the `<iframe>` navigates to in the `allow` attribute, the Permissions Policy that was applied to the original `<iframe>` will be applied to the origin the `<iframe>` navigates to.

Several features can be controlled at the same time by including a semi-colon-separated list of policy directives inside the `allow` attribute.

```html
<iframe
 src="https://example.com"
 allow="geolocation 'self' https://a.example.com https://b.example.com; fullscreen 'none'"></iframe>
```

It is worth giving the `src` value a special mention. We mentioned above that using this allowlist value will mean that the associated feature will be allowed in this `<iframe>`, as long as the document loaded into it comes from the same origin as the URL in its src attribute. This value is the *default* `allowlist` value for features listed in `allow`, so the following are equivalent:

```html
<iframe src="https://example.com" allow="geolocation 'src'">
  <iframe src="https://example.com" allow="geolocation"></iframe
></iframe>
```

**Note:** As you'll have noticed, the syntax for `<iframe>` policies is a bit different to the syntax for `Permissions-Policy` headers. The former still uses the same syntax as the older Feature Policy specification, which was superseded by Permissions Policy.

Inheritance of policies for embedded content
--------------------------------------------

Scripts inherit the policy of their browsing context, regardless of their origin. That means that top-level scripts inherit the policy from the main document.

All `<iframe>`s inherit the policy of their parent page. If the `<iframe>` has an `allow` attribute *and* the parent page has a `Permissions-Policy`, the policies of the parent page and the `allow` attribute are combined, using the most restrictive subset. For an `<iframe>` to have a feature enabled, the origin must be in the allowlist for both the parent page and the `allow` attribute.

Disabling a feature in a policy is a one-way toggle. If a feature has been disabled for a child frame by its parent frame, the child cannot re-enable it, and neither can any of the child's descendants.

Examples
--------

### Combining HTTP header and `<iframe>` policies

For example, let's say that we wanted to enable geolocation usage on our own origin, and in embedded content coming from our trusted ad network. We could set up the page-wide Permissions Policy like this:

```http
Permissions-Policy: geolocation=(self https://trusted-ad-network.com)
```

Over in our ad `<iframe>`s, we could set access to the `https://trusted-ad-network.com` origin like this:

```html
<iframe src="https://trusted-ad-network.com" allow="geolocation"></iframe>
```

If a different origin ended up getting loaded into `<iframe>`, it would not have access to geolocation:

```html
<iframe src="https://rogue-origin-example.com" allow="geolocation"></iframe>
```

Specifications
--------------

| Specification |
| --- |
| Permissions Policy # permissions-policy-http-header-field |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `Permissions-Policy` HTTP header
* allow attribute on iframes
* Controlling browser features with Permissions Policy: use guide that also contains several demo links.
* Permissions/Feature policies on chromestatus.com
* Privacy, permissions, and information security


Configuring servers for Ogg media - HTTP

Configuring servers for Ogg media
=================================

 HTML `<audio>` and `<video>` elements allow media presentation without the need for the user to install any plug-ins or other software to do so.
 This guide covers a few server configuration changes that may be necessary for your web server to correctly serve Ogg media files.
 This information may also be useful if you encounter other media types your server isn't already configured to recognize.

Serve media with the correct MIME type
--------------------------------------

`*.ogg` and `*.ogv` files containing video (possibly with an audio track as well, of course), should be served with the `video/ogg` MIME type. `*.oga` and `*.ogg` files containing only audio should be served with the `audio/ogg` MIME type.

If you don't know whether the Ogg file contains audio or video, you can serve it with the MIME type `application/ogg`, and the browser will treat it as a video file.

Most servers don't by default serve Ogg media with the correct MIME types, so you'll likely need to add the appropriate configuration for this.

For Apache, you can add the following to your configuration:
```

AddType audio/ogg .oga
AddType video/ogg .ogv
AddType application/ogg .ogg
```

You can find specific information about possible media file types and the codecs used within them in our comprehensive guide to media types and formats on the web. In particular, the article on media container formats will be especially helpful when configuring servers to host media properly.

Handle HTTP 1.1 byte range requests correctly
---------------------------------------------

 In order to support seeking and playing back regions of the media that aren't yet downloaded, Firefox uses HTTP 1.1 byte-range requests to retrieve the media from the seek target position.
 In addition, it uses byte-range requests to seek to the end of the media (assuming you serve the `Content-Length` header) in order to determine the duration of the media.

 Your server should accept the `Accept-Ranges``: bytes` HTTP header if it can accept byte-range requests. It must return `206``: Partial content` to all byte range requests; otherwise, browsers can't be sure you actually support byte range requests.
 Your server must also return `206: Partial Content` for the request `Range: bytes=0-` as well.

For more information, see HTTP range requests.

Include regular key frames
--------------------------

When the browser seeks through Ogg media to a specified time, it has to seek to the nearest key frame before the seek target, then download and decode the video from there until the requested target time. The farther apart your key frames are, the longer this takes, so it's helpful to include key frames at regular intervals.

By default, `ffmpeg2theora` uses one key frame every 64 frames (or about every 2 seconds at 30 frames per second), which works pretty well.

**Note:** Of course, the more key frames you use, the larger your video file is, so you may need to experiment a bit to get the right balance between file size and seek performance.

Consider using the preload attribute
------------------------------------

The HTML `<audio>` and `<video>` elements provide the `preload` attribute, which tells the browser to attempt to download the entire media when the page loads. Without `preload`, the browser only downloads enough of the media to display the first video frame, and to determine the media's duration.

`preload` is off by default, so if getting to video is the point of your web page, your users may appreciate it if you include `preload` in your video elements. Using `preload="metadata"` will preload the media file's metadata and possibly the first few frames of video. Setting `payload` to `auto` tells the browser to automatically begin downloading the media as soon as the page is loaded, under the assumption that the user will play it.

Configuration for older Firefox versions
----------------------------------------

### Serve X-Content-Duration headers

**Note:** As of Firefox 41, the `X-Content-Duration` header is no longer supported. See Firefox bug 1160695 for more details.

The Ogg format doesn't encapsulate the duration of media, so for the progress bar on the video controls to display the duration of the video, Gecko needs to determine the length of the media using other means.

There are two ways Gecko can do this. The best way is to offer an `X-Content-Duration` header when serving Ogg media files. This header provides the duration of the video in seconds (**not** in HH:MM:SS format) as a floating-point value.

For example, if the video is 1 minute and 32.6 seconds long, this header would be:

```http
X-Content-Duration: 92.6
```

If your server provides the `X-Content-Duration` header when serving Ogg media, Gecko doesn't have to do any extra HTTP requests to seek to the end of the file to calculate its duration. This makes the entire process much more efficient as well as more accurate.

As an inferior alternative, Gecko can estimate the video length based on the Content-Length. See next point.

### Don't use HTTP compression for media files

One common way to reduce the load on a web server is to use gzip or deflate compression when serving to a supporting web browser.

Although it's unlikely, it's possible the browser may advertise that it supports HTTP compression (gzip/deflate) using the `Accept-Encoding: gzip,deflate` header when requesting media files. Your server should be configured to not do so. The data in media files is already compressed, so you won't get any real benefit from compression, and the use of compression makes it impossible for the browser to properly seek the video or determine its duration.

Another problem with allowing HTTP compression for media streaming: Apache servers don't send the `Content-Length` response header if gzip encoding is used.

### Getting the duration of Ogg media

You can use the `oggz-info` tool to get the media duration; this tool is included with the `oggz-tools` package. The output from `oggz-info` looks like this:
```

$ oggz-info /g/media/bruce_vs_ironman.ogv
Content-Duration: 00:01:00.046

Skeleton: serialno 1976223438
        4 packets in 3 pages, 1.3 packets/page, 27.508% Ogg overhead
        Presentation-Time: 0.000
        Basetime: 0.000

Theora: serialno 0170995062
        1790 packets in 1068 pages, 1.7 packets/page, 1.049% Ogg overhead
        Video-Framerate: 29.983 fps
        Video-Width: 640
        Video-Height: 360

Vorbis: serialno 0708996688
        4531 packets in 167 pages, 27.1 packets/page, 1.408% Ogg overhead
        Audio-Samplerate: 44100 Hz
        Audio-Channels: 2
```

Note that you can't serve up the reported Content-Duration line reported by `oggz-info`, because it's reported in HH:MM:SS format. You'll need to convert it to seconds only, then serve that as your `X-Content-Duration` value. Just parse out the HH, MM, and SS into numbers, then do (HH\*3600)+(MM\*60)+SS to get the value you should report.

It's important to note that it appears that `oggz-info` makes a read pass of the media in order to calculate its duration, so it's a good idea to store the duration value in order to avoid lengthy delays while the value is calculated for every HTTP request of your Ogg media.

See also
--------

* Guide to media types and formats on the web
* Video and audio content
* Codecs in common media types


HTTP Client hints - HTTP

HTTP Client hints
=================

**Client hints** are a set of HTTP request header fields that a server can proactively request from a client to get information about the device, network, user, and user-agent-specific preferences.
 The server can determine which resources to send, based on the information that the client chooses to provide.

The set of "hint" headers are listed in the topic HTTP Headers and summarized below.

Overview
--------

 A server must announce that it supports client hints, using the `Accept-CH` header to specify the hints that it is interested in receiving.
 When a client that supports client hints receives the `Accept-CH` header it can choose to append some or all of the listed client hint headers in its subsequent requests.

For example, following `Accept-CH` in a response below, the client could append `Width`, `Downlink` and `Sec-CH-UA` headers to all subsequent requests.

```http
Accept-CH: Width, Downlink, Sec-CH-UA
```

 This approach is efficient in that the server only requests the information that it is able to usefully handle.
 It is also relatively "privacy-preserving", in that it is up to the client to decide what information it can safely share.

There is a small set of low entropy client hint headers that may be sent by a client even if not requested.

**Note:** Client hints can also be specified in HTML using the `<meta>` element with the `http-equiv` attribute.

```html
<meta http-equiv="Accept-CH" content="Width, Downlink, Sec-CH-UA" />
```

Caching and Client Hints
------------------------

 Client hints that determine which resources are sent in responses should generally also be included in the affected response's `Vary` header.
 This ensures that a different resource is cached for every different value of the hint header.

```http
Vary: Accept, Width, ECT
```

 You may prefer to omit specifying `Vary` or use some other strategy for client hint headers where the value changes a lot, as this effectively makes the resource uncacheable. (A new cache entry is created for every unique value.)
 This applies in particular to network client hints like `Downlink` and `RTT`.
 For more information see HTTP Caching > Vary.

Hint life-time
--------------

 A server specifies the client hint headers that it is interested in getting in the `Accept-CH` response header.
 The user agent appends the requested client hint headers, or at least the subset that it wants to share with that server, to all subsequent requests in the current browsing session.

In other words, the request for a specific set of hints does not expire until the browser is shut down.

 A server can replace the set of client hints it is interested in receiving by resending the `Accept-CH` response header with a new list.
 For example, to stop requesting any hints it would send `Accept-CH` with an empty list.

**Note:** The client hints set for a particular origin can also be cleared by sending a `Clear-Site-Data: "clientHints"` response header for a URL inside that origin.

Low entropy hints
-----------------

Client hints are broadly divided into high and low entropy hints.

 The low entropy hints are those that don't give away much information that might be used to create a fingerprinting for a user.
 They may be sent by default on every client request, irrespective of the server `Accept-CH` response header, depending on the permission policy.
 These hints include: `Save-Data`, `Sec-CH-UA`, `Sec-CH-UA-Mobile`, `Sec-CH-UA-Platform`.

 The high entropy hints are those that have the potential to give away more information that can be used for user fingerprinting, and therefore are gated in such a way that the user agent can make a decision whether to provide them.
 The decision might be based on user preferences, a permission request, or the permission policy.
 All client hints that are not low entropy hints are considered high entropy hints.

Critical client hints
---------------------

 A *critical client hint* is one where applying the response may significantly change the rendered page, potentially in a way that is jarring or will affect usability, and therefore which must be applied before the content is rendered.
 For example, `Sec-CH-Prefers-Reduced-Motion` is commonly treated as a critical hint, because it might markedly affect the behavior of animations, and because a user who chooses this preference needs it to be set.

 A server can use the `Critical-CH` response header along with `Accept-CH` to specify that an accepted client hint is also a critical client hint (a header in `Critical-CH` must also appear in `Accept-CH`).
 User agents receiving a response with `Critical-CH` must check if the indicated critical headers were sent in the original request. If not, then the user agent will retry the request rather than render the page.
 This approach ensures that client preferences set using critical client hints are always used, even if not included in the first request, or if the server configuration changes.

For example, in this case, the server tells a client via `Accept-CH` that it accepts `Sec-CH-Prefers-Reduced-Motion`, and `Critical-CH` is used to specify that `Sec-CH-Prefers-Reduced-Motion` is considered a critical client hint:

```http
HTTP/1.1 200 OK
Content-Type: text/html
Accept-CH: Sec-CH-Prefers-Reduced-Motion
Vary: Sec-CH-Prefers-Reduced-Motion
Critical-CH: Sec-CH-Prefers-Reduced-Motion
```

**Note:** We've also specified `Sec-CH-Prefers-Reduced-Motion` in the `Vary` header to indicate to the browser that the served content will differ based on this header value, even if the URL stays the same, so the browser shouldn't just use an existing cached response and instead should cache this response separately. Each header listed in the `Critical-CH` header should also be present in the `Accept-CH` and `Vary` headers.

As `Sec-CH-Prefers-Reduced-Motion` is a critical hint that was not in the original request, the client automatically retries the request — this time telling the server via `Sec-CH-Prefers-Reduced-Motion` that it has a user preference for reduced-motion animations.

```http
GET / HTTP/1.1
Host: example.com
Sec-CH-Prefers-Reduced-Motion: "reduce"
```

Hint types
----------

### User-agent client hints

 User agent (UA) client hint headers allow a server to vary responses based on the user agent (browser), operating system, and device.
 Headers include: `Sec-CH-UA`, `Sec-CH-UA-Arch`, `Sec-CH-UA-Bitness`, `Sec-CH-UA-Full-Version-List`, `Sec-CH-UA-Full-Version`, `Sec-CH-UA-Mobile`, `Sec-CH-UA-Model`, `Sec-CH-UA-Platform`, and `Sec-CH-UA-Platform-Version`.

Client hints are available to web page JavaScript via the User Agent Client Hints API.

**Note:** Servers currently get most of the same information by parsing the `User-Agent` header.
 For historical reasons this header contains a lot of largely irrelevant information, and information that might be used to identify a *particular user*.
 UA client hints provide a more efficient and privacy preserving way of getting the desired information.
 They are eventually expected to replace this older approach.

### User preference media features client hints

 User Preference Media Features Client Hints allow a server to vary responses based on a user agent's preferences for CSS media features such as color scheme or reduced motion.
 Headers include: `Sec-CH-Prefers-Reduced-Motion`, `Sec-CH-Prefers-Color-Scheme`.

### Device client hints

 Device client hints allow a server to vary responses based on device characteristics including available memory and screen properties.
 Headers include: `Device-Memory`, `Width`, `Viewport-Width`.

### Network client hints

 Network client hints allow a server to vary responses based on the user's choice, network bandwidth, and latency.
 Headers include: `Save-Data`, `Downlink`, `ECT`, `RTT`.

See also
--------

* Client Hints headers
* `Vary` HTTP Header
* Client Hints Infrastructure
* User Agent Client Hints API
* Improving user privacy and developer experience with User-Agent Client Hints (developer.chrome.com)


HTTP headers - HTTP

HTTP headers
============

**HTTP headers** let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (`:`), then by its value. Whitespace before the value is ignored.

Custom proprietary headers have historically been used with an `X-` prefix, but this convention was deprecated in June 2012 because of the inconveniences it caused when nonstandard fields became standard in RFC 6648; others are listed in an IANA registry, whose original content was defined in RFC 4229. IANA also maintains a registry of proposed new HTTP headers.

Headers can be grouped according to their contexts:

Request headers

Contain more information about the resource to be fetched, or about the client requesting the resource.

Response headers

Hold additional information about the response, like its location or about the server providing it.

Representation headers

Contain information about the body of the resource, like its MIME type, or encoding/compression applied.

Payload headers

Contain representation-independent information about payload data, including content length and the encoding used for transport.

Headers can also be grouped according to how proxies handle them:

End-to-end headers

These headers *must* be transmitted to the final recipient of the message: the server for a request, or the client for a response. Intermediate proxies must retransmit these headers unmodified and caches must store them.

Hop-by-hop headers

These headers are meaningful only for a single transport-level connection, and *must not* be retransmitted by proxies or cached. Note that only hop-by-hop headers may be set using the `Connection` header.

Authentication
--------------

`WWW-Authenticate`

Defines the authentication method that should be used to access a resource.

`Authorization`

Contains the credentials to authenticate a user-agent with a server.

`Proxy-Authenticate`

Defines the authentication method that should be used to access a resource behind a proxy server.

`Proxy-Authorization`

Contains the credentials to authenticate a user agent with a proxy server.

Caching
-------

`Age`

The time, in seconds, that the object has been in a proxy cache.

`Cache-Control`

Directives for caching mechanisms in both requests and responses.

`Clear-Site-Data`

Clears browsing data (e.g. cookies, storage, cache) associated with the requesting website.

`Expires`

The date/time after which the response is considered stale.

Conditionals
------------

`Last-Modified`

The last modification date of the resource, used to compare several versions of the same resource. It is less accurate than `ETag`, but easier to calculate in some environments. Conditional requests using `If-Modified-Since` and `If-Unmodified-Since` use this value to change the behavior of the request.

`ETag`

A unique string identifying the version of the resource. Conditional requests using `If-Match` and `If-None-Match` use this value to change the behavior of the request.

`If-Match`

Makes the request conditional, and applies the method only if the stored resource matches one of the given ETags.

`If-None-Match`

Makes the request conditional, and applies the method only if the stored resource *doesn't* match any of the given ETags. This is used to update caches (for safe requests), or to prevent uploading a new resource when one already exists.

`If-Modified-Since`

Makes the request conditional, and expects the resource to be transmitted only if it has been modified after the given date. This is used to transmit data only when the cache is out of date.

`If-Unmodified-Since`

Makes the request conditional, and expects the resource to be transmitted only if it has not been modified after the given date. This ensures the coherence of a new fragment of a specific range with previous ones, or to implement an optimistic concurrency control system when modifying existing documents.

`Vary`

Determines how to match request headers to decide whether a cached response can be used rather than requesting a fresh one from the origin server.

Connection management
---------------------

`Connection`

Controls whether the network connection stays open after the current transaction finishes.

`Keep-Alive`

Controls how long a persistent connection should stay open.

Content negotiation
-------------------

For more details, refer to the Content negotiation article.

`Accept`

Informs the server about the types of data that can be sent back.

`Accept-Encoding`

The encoding algorithm, usually a compression algorithm, that can be used on the resource sent back.

`Accept-Language`

Informs the server about the human language the server is expected to send back. This is a hint and is not necessarily under the full control of the user: the server should always pay attention not to override an explicit user choice (like selecting a language from a dropdown).

Controls
--------

`Expect`

Indicates expectations that need to be fulfilled by the server to properly handle the request.

`Max-Forwards`

When using `TRACE`, indicates the maximum number of hops the request can do before being reflected to the sender.

Cookies
-------

`Cookie`

Contains stored HTTP cookies previously sent by the server with the `Set-Cookie` header.

`Set-Cookie`

Send cookies from the server to the user-agent.

CORS
----

For more information, refer to the CORS documentation.

`Access-Control-Allow-Credentials`

Indicates whether the response to the request can be exposed when the credentials flag is true.

`Access-Control-Allow-Headers`

Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request.

`Access-Control-Allow-Methods`

Specifies the methods allowed when accessing the resource in response to a preflight request.

`Access-Control-Allow-Origin`

Indicates whether the response can be shared.

`Access-Control-Expose-Headers`

Indicates which headers can be exposed as part of the response by listing their names.

`Access-Control-Max-Age`

Indicates how long the results of a preflight request can be cached.

`Access-Control-Request-Headers`

Used when issuing a preflight request to let the server know which HTTP headers will be used when the actual request is made.

`Access-Control-Request-Method`

Used when issuing a preflight request to let the server know which HTTP method will be used when the actual request is made.

`Origin`

Indicates where a fetch originates from.

`Timing-Allow-Origin`

Specifies origins that are allowed to see values of attributes retrieved via features of the Resource Timing API, which would otherwise be reported as zero due to cross-origin restrictions.

Downloads
---------

`Content-Disposition`

Indicates if the resource transmitted should be displayed inline (default behavior without the header), or if it should be handled like a download and the browser should present a "Save As" dialog.

Message body information
------------------------

`Content-Length`

The size of the resource, in decimal number of bytes.

`Content-Type`

Indicates the media type of the resource.

`Content-Encoding`

Used to specify the compression algorithm.

`Content-Language`

Describes the human language(s) intended for the audience, so that it allows a user to differentiate according to the users' own preferred language.

`Content-Location`

Indicates an alternate location for the returned data.

Proxies
-------

`Forwarded`

Contains information from the client-facing side of proxy servers that is altered or lost when a proxy is involved in the path of the request.

`Via`

Added by proxies, both forward and reverse proxies, and can appear in the request headers and the response headers.

Redirects
---------

`Location`

Indicates the URL to redirect a page to.

`Refresh`

Directs the browser to reload the page or redirect to another. Takes the same value as the `meta` element with `http-equiv="refresh"`.

Request context
---------------

`From`

Contains an Internet email address for a human user who controls the requesting user agent.

`Host`

Specifies the domain name of the server (for virtual hosting), and (optionally) the TCP port number on which the server is listening.

`Referer`

The address of the previous web page from which a link to the currently requested page was followed.

`Referrer-Policy`

Governs which referrer information sent in the `Referer` header should be included with requests made.

`User-Agent`

Contains a characteristic string that allows the network protocol peers to identify the application type, operating system, software vendor or software version of the requesting software user agent.

Response context
----------------

`Allow`

Lists the set of HTTP request methods supported by a resource.

`Server`

Contains information about the software used by the origin server to handle the request.

Range requests
--------------

`Accept-Ranges`

Indicates if the server supports range requests, and if so in which unit the range can be expressed.

`Range`

Indicates the part of a document that the server should return.

`If-Range`

Creates a conditional range request that is only fulfilled if the given etag or date matches the remote resource. Used to prevent downloading two ranges from incompatible version of the resource.

`Content-Range`

Indicates where in a full body message a partial message belongs.

Security
--------

`Cross-Origin-Embedder-Policy` (COEP)

Allows a server to declare an embedder policy for a given document.

`Cross-Origin-Opener-Policy` (COOP)

Prevents other domains from opening/controlling a window.

`Cross-Origin-Resource-Policy` (CORP)

Prevents other domains from reading the response of the resources to which this header is applied. See also CORP explainer article.

`Content-Security-Policy` (CSP)

Controls resources the user agent is allowed to load for a given page.

`Content-Security-Policy-Report-Only`

Allows web developers to experiment with policies by monitoring, but not enforcing, their effects. These violation reports consist of JSON documents sent via an HTTP `POST` request to the specified URI.

`Permissions-Policy`

Provides a mechanism to allow and deny the use of browser features in a website's own frame, and in `<iframe>`s that it embeds.

`Strict-Transport-Security` (HSTS)

Force communication using HTTPS instead of HTTP.

`Upgrade-Insecure-Requests`

Sends a signal to the server expressing the client's preference for an encrypted and authenticated response, and that it can successfully handle the `upgrade-insecure-requests` directive.

`X-Content-Type-Options`

Disables MIME sniffing and forces browser to use the type given in `Content-Type`.

`X-Frame-Options` (XFO)

Indicates whether a browser should be allowed to render a page in a `<frame>`, `<iframe>`, `<embed>` or `<object>`.

`X-Permitted-Cross-Domain-Policies`

Specifies if a cross-domain policy file (`crossdomain.xml`) is allowed. The file may define a policy to grant clients, such as Adobe's Flash Player (now obsolete), Adobe Acrobat, Microsoft Silverlight (now obsolete), or Apache Flex, permission to handle data across domains that would otherwise be restricted due to the Same-Origin Policy. See the Cross-domain Policy File Specification for more information.

`X-Powered-By`

May be set by hosting environments or other frameworks and contains information about them while not providing any usefulness to the application or its visitors. Unset this header to avoid exposing potential vulnerabilities.

`X-XSS-Protection`

Enables cross-site scripting filtering.

### Fetch metadata request headers

Fetch metadata request headers provide information about the context from which the request originated. A server can use them to make decisions about whether a request should be allowed, based on where the request came from and how the resource will be used.

`Sec-Fetch-Site`

Indicates the relationship between a request initiator's origin and its target's origin. It is a Structured Header whose value is a token with possible values `cross-site`, `same-origin`, `same-site`, and `none`.

`Sec-Fetch-Mode`

Indicates the request's mode to a server. It is a Structured Header whose value is a token with possible values `cors`, `navigate`, `no-cors`, `same-origin`, and `websocket`.

`Sec-Fetch-User`

Indicates whether or not a navigation request was triggered by user activation. It is a Structured Header whose value is a boolean so possible values are `?0` for false and `?1` for true.

`Sec-Fetch-Dest`

Indicates the request's destination. It is a Structured Header whose value is a token with possible values `audio`, `audioworklet`, `document`, `embed`, `empty`, `font`, `image`, `manifest`, `object`, `paintworklet`, `report`, `script`, `serviceworker`, `sharedworker`, `style`, `track`, `video`, `worker`, and `xslt`.

The following request headers are not *strictly* "fetch metadata request headers", but similarly provide information about the context of how a resource will be used. A server might use them to modify its caching behavior, or the information that is returned:

`Sec-Purpose`

Indicates the purpose of the request, when the purpose is something other than immediate use by the user-agent. The header currently has one possible value, `prefetch`, which indicates that the resource is being fetched preemptively for a possible future navigation.

`Service-Worker-Navigation-Preload`

A request header sent in preemptive request to `fetch()` a resource during service worker boot. The value, which is set with `NavigationPreloadManager.setHeaderValue()`, can be used to inform a server that a different resource should be returned than in a normal `fetch()` operation.

Server-sent events
------------------

`Report-To`

Used to specify a server endpoint for the browser to send warning and error reports to.

Transfer coding
---------------

`Transfer-Encoding`

Specifies the form of encoding used to safely transfer the resource to the user.

`TE`

Specifies the transfer encodings the user agent is willing to accept.

`Trailer`

Allows the sender to include additional fields at the end of chunked message.

Other
-----

`Alt-Svc`

Used to list alternate ways to reach this service.

`Alt-Used`

Used to identify the alternative service in use.

`Date`

Contains the date and time at which the message was originated.

`Link`

This entity-header field provides a means for serializing one or more links in HTTP headers. It is semantically equivalent to the HTML `<link>` element.

`Retry-After`

Indicates how long the user agent should wait before making a follow-up request.

`Server-Timing`

Communicates one or more metrics and descriptions for the given request-response cycle.

`Service-Worker-Allowed`

Used to remove the path restriction by including this header in the response of the Service Worker script.

`SourceMap`

Links generated code to a source map.

`Upgrade`

This HTTP/1.1 (only) header can be used to upgrade an already established client/server connection to a different protocol (over the same transport protocol). For example, it can be used by a client to upgrade a connection from HTTP 1.1 to HTTP 2.0, or an HTTP or HTTPS connection into a WebSocket.

Experimental headers
--------------------

### Client hints

HTTP Client hints are a set of request headers that provide useful information about the client such as device type and network conditions, and allow servers to optimize what is served for those conditions.

Servers proactively requests the client hint headers they are interested in from the client using `Accept-CH`. The client may then choose to include the requested headers in subsequent requests.

`Accept-CH`
Experimental

Servers can advertise support for Client Hints using the `Accept-CH` header field or an equivalent HTML `<meta>` element with `http-equiv` attribute.

`Critical-CH`
Experimental

Servers use `Critical-CH` along with `Accept-CH` to specify that accepted client hints are also critical client hints.

The different categories of client hints are listed below.

#### User agent client hints

The UA client hints are request headers that provide information about the user agent, the platform/architecture it is running on, and user preferences set on the user agent or platform:

`Sec-CH-UA`
Experimental

User agent's branding and version.

`Sec-CH-UA-Arch`
Experimental

User agent's underlying platform architecture.

`Sec-CH-UA-Bitness`
Experimental

User agent's underlying CPU architecture bitness (for example "64" bit).

`Sec-CH-UA-Full-Version-List`
Experimental

Full version for each brand in the user agent's brand list.

`Sec-CH-UA-Mobile`
Experimental

User agent is running on a mobile device or, more generally, prefers a "mobile" user experience.

`Sec-CH-UA-Model`
Experimental

User agent's device model.

`Sec-CH-UA-Platform`
Experimental

User agent's underlying operation system/platform.

`Sec-CH-UA-Platform-Version`
Experimental

User agent's underlying operation system version.

`Sec-CH-UA-Prefers-Color-Scheme`
Experimental

User's preference of dark or light color scheme.

`Sec-CH-UA-Prefers-Reduced-Motion`
Experimental

User's preference to see fewer animations and content layout shifts.

#### Device client hints

`Device-Memory`
Experimental

Approximate amount of available client RAM memory. This is part of the Device Memory API.

#### Network client hints

Network client hints allow a server to choose what information is sent based on the user choice and network bandwidth and latency.

`Downlink`
Experimental

Approximate bandwidth of the client's connection to the server, in Mbps. This is part of the Network Information API.

`ECT`
Experimental

The effective connection type ("network profile") that best matches the connection's latency and bandwidth. This is part of the Network Information API.

`RTT`
Experimental

Application layer round trip time (RTT) in milliseconds, which includes the server processing time. This is part of the Network Information API.

`Save-Data`
Experimental

A string `on` that indicates the user agent's preference for reduced data usage.

### Privacy

`Sec-GPC`
Non-standard

Experimental

Indicates whether the user consents to a website or service selling or sharing their personal information with third parties.

### Security

`Origin-Isolation`
Experimental

Provides a mechanism to allow web applications to isolate their origins.

### Server-sent events

`NEL`
Experimental

Defines a mechanism that enables developers to declare a network error reporting policy.

### Other

`Accept-Push-Policy`
Experimental

A client can express the desired push policy for a request by sending an `Accept-Push-Policy` header field in the request.

`Accept-Signature`
Experimental

A client can send the `Accept-Signature` header field to indicate intention to take advantage of any available signatures and to indicate what kinds of signatures it supports.

`Early-Data`
Experimental

Indicates that the request has been conveyed in TLS early data.

`Push-Policy`
Experimental

A `Push-Policy` defines the server behavior regarding push when processing a request.

`Signature`
Experimental

The `Signature` header field conveys a list of signatures for an exchange, each one accompanied by information about how to determine the authority of and refresh that signature.

`Signed-Headers`
Experimental

The `Signed-Headers` header field identifies an ordered list of response header fields to include in a signature.

`Supports-Loading-Mode`
Experimental

Set by a navigation target to opt-in to using various higher-risk loading modes. For example, cross-origin, same-site prerendering requires a `Supports-Loading-Mode` value of `credentialed-prerender`.

Non-standard headers
--------------------

`X-Forwarded-For`
Non-standard

Identifies the originating IP addresses of a client connecting to a web server through an HTTP proxy or a load balancer.

`X-Forwarded-Host`
Non-standard

Identifies the original host requested that a client used to connect to your proxy or load balancer.

`X-Forwarded-Proto`
Non-standard

Identifies the protocol (HTTP or HTTPS) that a client used to connect to your proxy or load balancer.

`X-DNS-Prefetch-Control`
Non-standard

Controls DNS prefetching, a feature by which browsers proactively perform domain name resolution on both links that the user may choose to follow as well as URLs for items referenced by the document, including images, CSS, JavaScript, and so forth.

`X-Robots-Tag`
Non-standard

The `X-Robots-Tag` HTTP header is used to indicate how a web page is to be indexed within public search engine results. The header is effectively equivalent to `<meta name="robots" content="…">`.

Deprecated headers
------------------

`Pragma`
Deprecated

Implementation-specific header that may have various effects anywhere along the request-response chain. Used for backwards compatibility with HTTP/1.0 caches where the `Cache-Control` header is not yet present.

`Warning`
Deprecated

General warning information about possible problems.

Contributing
------------

You can help by writing new entries or improving the existing ones.

See also
--------

* Wikipedia page on List of HTTP headers
* IANA registry
* HTTP Working Group


Using HTTP cookies - HTTP

Using HTTP cookies
==================

 An **HTTP cookie** (web cookie, browser cookie) is a small piece of data that a server sends to a user's web browser.
 The browser may store the cookie and send it back to the same server with later requests.
 Typically, an HTTP cookie is used to tell if two requests come from the same browser—keeping a user logged in, for example. It remembers stateful information for the stateless HTTP protocol.

Cookies are mainly used for three purposes:

Session management

Logins, shopping carts, game scores, or anything else the server should remember

Personalization

User preferences, themes, and other settings

Tracking

Recording and analyzing user behavior

Cookies were once used for general client-side storage. While this made sense when they were the only way to store data on the client, modern storage APIs are now recommended. Cookies are sent with every request, so they can worsen performance (especially for mobile data connections). Modern APIs for client storage are the Web Storage API (`localStorage` and `sessionStorage`) and IndexedDB.

**Note:** To see stored cookies (and other storage that a web page can use), you can enable the Storage Inspector in Developer Tools and select Cookies from the storage tree.

Creating cookies
----------------

After receiving an HTTP request, a server can send one or more `Set-Cookie` headers with the response. The browser usually stores the cookie and sends it with requests made to the same server inside a `Cookie` HTTP header. You can specify an expiration date or time period after which the cookie shouldn't be sent. You can also set additional restrictions to a specific domain and path to limit where the cookie is sent. For details about the header attributes mentioned below, refer to the `Set-Cookie` reference article.

### The `Set-Cookie` and `Cookie` headers

The `Set-Cookie` HTTP response header sends cookies from the server to the user agent. A simple cookie is set like this:

```http
Set-Cookie: <cookie-name>=<cookie-value>
```

This instructs the server sending headers to tell the client to store a pair of cookies:

```http
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy\_cookie=choco
Set-Cookie: tasty\_cookie=strawberry

[page content]
```

Then, with every subsequent request to the server, the browser sends all previously stored cookies back to the server using the `Cookie` header.

```http
GET /sample\_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy\_cookie=choco; tasty\_cookie=strawberry
```

**Note:** Here's how to use the `Set-Cookie` header in various server-side applications:

* PHP
* Node.JS
* Python
* Ruby on Rails

### Define the lifetime of a cookie

Cookies can persist for two different periods, depending on the attributes used with the `Set-Cookie` header when they were created:

* *Permanent* cookies are deleted at a date specified by the `Expires` attribute or after a period prescribed by the `Max-Age` attribute.
* *Session* cookies – cookies without a `Max age` or `Expires` attribute – are deleted when the current session ends. The browser defines when the "current session" ends, and some browsers use *session restoring* when restarting. This can cause session cookies to last indefinitely.

For example:

```http
Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;
```

**Note:** When you set an `Expires` date and time, they're relative to the client the cookie is being set on, not the server.

If your site authenticates users, it should regenerate and resend session cookies, even ones that already exist, whenever a user authenticates. This approach helps prevent session fixation attacks, where a third party can reuse a user's session.

### Restrict access to cookies

You can ensure that cookies are sent securely and aren't accessed by unintended parties or scripts in one of two ways: with the `Secure` attribute and the `HttpOnly` attribute.

A cookie with the `Secure` attribute is only sent to the server with an encrypted request over the HTTPS protocol. It's never sent with unsecured HTTP (except on localhost), which means man-in-the-middle attackers can't access it easily. Insecure sites (with `http:` in the URL) can't set cookies with the `Secure` attribute. However, don't assume that `Secure` prevents all access to sensitive information in cookies. For example, someone with access to the client's hard disk (or JavaScript if the `HttpOnly` attribute isn't set) can read and modify the information.

A cookie with the `HttpOnly` attribute is inaccessible to the JavaScript `Document.cookie` API; it's only sent to the server. For example, cookies that persist in server-side sessions don't need to be available to JavaScript and should have the `HttpOnly` attribute. This precaution helps mitigate cross-site scripting (XSS) attacks.

Here's an example:

```http
Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly
```

### Define where cookies are sent

The `Domain` and `Path` attributes define the *scope* of a cookie: what URLs the cookies should be sent to.

#### Domain attribute

The `Domain` attribute specifies which server can receive a cookie.

If specified, then cookies are available on the server and its subdomains. For example, if you set `Domain=mozilla.org`, cookies are available on mozilla.org and its subdomains like `developer.mozilla.org`.

If the server does not specify a `Domain`, the cookies are available on the server *but not on its subdomains*. Therefore, specifying `Domain` is less restrictive than omitting it. However, it can be helpful when subdomains need to share information about a user.

#### Path attribute

 The `Path` attribute indicates a URL path that must exist in the requested URL in order to send the `Cookie` header.
 The `%x2F` ("/") character is considered a directory separator, and subdirectories match as well.

For example, if you set `Path=/docs`, these request paths match:

* `/docs`
* `/docs/`
* `/docs/Web/`
* `/docs/Web/HTTP`

But these request paths don't:

* `/`
* `/docsets`
* `/fr/docs`

##### Path default value

If the `Path` attribute is not set, its default value is computed from the path of the URI that set the cookie, as follows:

* If the path is empty, does not start with `"/"`, or contains no more than one `"/"` character, then the default value for `Path` is `"/"`.
* Otherwise, the default value for `Path` is the path from the start up to but not including the final `"/"` character.

 For example, if the cookie was set from `"https://example.org/a/b/c`, then the default value of `Path`
 would be `"/a/b"`.

#### SameSite attribute

 The `SameSite` attribute lets servers specify whether/when cookies are sent with cross-site requests (where Site is defined by the registrable domain and the *scheme*: http or https).
 This provides some protection against cross-site request forgery attacks (CSRF).
 It takes three possible values: `Strict`, `Lax`, and `None`.

 With `Strict`, the browser only sends the cookie with requests from the cookie's origin site.
 `Lax` is similar, except the browser also sends the cookie when the user *navigates* to the cookie's origin site (even if the user is coming from a different site).
 For example, by following a link from an external site. `None` specifies that cookies are sent on both originating and cross-site requests, but *only in secure contexts* (i.e., if `SameSite=None` then the `Secure` attribute must also be set).
 If no `SameSite` attribute is set, the cookie is treated as `Lax`.

Here's an example:

```http
Set-Cookie: mykey=myvalue; SameSite=Strict
```

**Note:** The standard related to `SameSite` recently changed (MDN documents the new behavior above).
 See the cookies Browser compatibility table for information about how the attribute is handled in specific browser versions:

* `SameSite=Lax` is the new default if `SameSite` isn't specified.
 Previously, cookies were sent for all requests by default.
* Cookies with `SameSite=None` must now also specify the `Secure` attribute (they require a secure context).
* Cookies from the same domain are no longer considered to be from the same site if sent using a different scheme (`http:` or `https:`).

#### Cookie prefixes

Because of the design of the cookie mechanism, a server can't confirm that a cookie was set from a secure origin or even tell *where* a cookie was originally set.

A vulnerable application on a subdomain can set a cookie with the `Domain` attribute, which gives access to that cookie on all other subdomains. This mechanism can be abused in a *session fixation* attack. See session fixation for primary mitigation methods.

As a defense-in-depth measure, however, you can use *cookie prefixes* to assert specific facts about the cookie. Two prefixes are available:

`__Host-`

If a cookie name has this prefix, it's accepted in a `Set-Cookie` header only if it's also marked with the `Secure` attribute, was sent from a secure origin, does *not* include a `Domain` attribute, and has the `Path` attribute set to `/`. This way, these cookies can be seen as "domain-locked".

`__Secure-`

If a cookie name has this prefix, it's accepted in a `Set-Cookie` header only if it's marked with the `Secure` attribute and was sent from a secure origin. This is weaker than the `__Host-` prefix.

The browser will reject cookies with these prefixes that don't comply with their restrictions. Note that this ensures that subdomain-created cookies with prefixes are either confined to the subdomain or ignored completely. As the application server only checks for a specific cookie name when determining if the user is authenticated or a CSRF token is correct, this effectively acts as a defense measure against session fixation.

**Note:** On the application server, the web application *must* check for the full cookie name including the prefix. User agents *do not* strip the prefix from the cookie before sending it in a request's `Cookie` header.

For more information about cookie prefixes and the current state of browser support, see the Prefixes section of the Set-Cookie reference article.

#### JavaScript access using Document.cookie

You can create new cookies via JavaScript using the `Document.cookie` property. You can access existing cookies from JavaScript as well if the `HttpOnly` flag isn't set.

```js
document.cookie = "yummy\_cookie=choco";
document.cookie = "tasty\_cookie=strawberry";
console.log(document.cookie);
// logs "yummy\_cookie=choco; tasty\_cookie=strawberry"
```

Cookies created via JavaScript can't include the `HttpOnly` flag.

Please note the security issues in the Security section below. Cookies available to JavaScript can be stolen through XSS.

Security
--------

**Note:** When you store information in cookies, keep in mind that all cookie values are visible to, and can be changed by, the end user. Depending on the application, you may want to use an opaque identifier that the server looks up, or investigate alternative authentication/confidentiality mechanisms such as JSON Web Tokens.

Ways to mitigate attacks involving cookies:

* Use the `HttpOnly` attribute to prevent access to cookie values via JavaScript.
* Cookies that are used for sensitive information (such as indicating authentication) should have a short lifetime, with the `SameSite` attribute set to `Strict` or `Lax`. (See SameSite attribute, above.) In browsers that support SameSite, this ensures that the authentication cookie isn't sent with cross-site requests. This would make the request effectively unauthenticated to the application server.
Tracking and privacy
--------------------

### Third-party cookies

 A cookie is associated with a particular domain and scheme (such as `http` or `https`), and may also be associated with subdomains if the `Set-Cookie` `Domain` attribute is set.
 If the cookie domain and scheme match the current page, the cookie is considered to be from the same site as the page, and is referred to as a *first-party cookie*.

 If the domain and scheme are different, the cookie is not considered to be from the same site, and is referred to as a *third-party cookie*.
 While the server hosting a web page sets first-party cookies, the page may contain components stored on servers in other domains, such as images or other documents embedded in `<iframe>`s. These components may set third-party cookies.

**Note:** Third-party cookies are sometimes referred to as *cross-site cookies*. This is arguably a more accurate name, as *third-party cookies* imply ownership by a third-party company or organization. However, the behavior and potential issues are the same whether or not you own all the involved sites.

Typical use cases for third-party cookies include sharing user profile information or collecting analytics across different related domains. They are also often used for advertising and tracking users across the web.

**Note:** Companies should disclose the types of cookies they use on their sites for transparency purposes and to comply with regulations. For example, see Google's notice on the types of cookies it uses and Mozilla's Websites, Communications & Cookies Privacy Notice.

 A third-party server can create a profile of a user's browsing history and habits based on cookies sent to it by the same browser when accessing multiple sites.
 Firefox, by default, blocks third-party cookies that are known to contain trackers.
 Third-party cookies (or just tracking cookies) may also be blocked by other browser settings or extensions.
 Cookie blocking can cause some third-party components (such as social media widgets) not to function as intended.

There are some useful features available for developers who wish to respect user privacy, and minimize third-party tracking:

* Servers can (and should) set the cookie SameSite attribute to specify whether or not third-party cookies may be sent.
* Cookies Having Independent Partitioned State (CHIPS) enables developers to opt-in their cookies to partitioned storage, with a separate cookie jar per top-level site. This enables valid non-tracking uses of third-party cookies to continue working in browsers that do not allow cookies to be used for third-party tracking.
### Cookie-related regulations

Legislation or regulations that cover the use of cookies include:

* The General Data Privacy Regulation (GDPR) in the European Union
* The ePrivacy Directive in the EU
* The California Consumer Privacy Act

These regulations have global reach. They apply to any site on the *World Wide* Web that users from these jurisdictions access (the EU and California, with the caveat that California's law applies only to entities with gross revenue over 25 million USD, among things).

These regulations include requirements such as:

* Notifying users that your site uses cookies.
* Allowing users to opt out of receiving some or all cookies.
* Allowing users to use the bulk of your service without receiving cookies.

There may be other regulations that govern the use of cookies in your locality. The burden is on you to know and comply with these regulations. There are companies that offer "cookie banner" code that helps you comply with these regulations.

Other ways to store information in the browser
----------------------------------------------

Another approach to storing data in the browser is the Web Storage API. The window.sessionStorage and window.localStorage properties correspond to session and permanent cookies in duration, but have larger storage limits than cookies, and are never sent to a server. More structured and larger amounts of data can be stored using the IndexedDB API, or a library built on it.

There are some techniques designed to recreate cookies after they're deleted. These are known as "zombie" cookies. These techniques violate the principles of user privacy and user control, may violate data privacy regulations, and could expose a website using them to legal liability.

See also
--------

* `Set-Cookie`
* `Cookie`
* `Document.cookie`
* `Navigator.cookieEnabled`
* Inspecting cookies using the Storage Inspector
* Cookie specification: RFC 6265
* HTTP cookie on Wikipedia
* Cookies, the GDPR, and the ePrivacy Directive


Browser detection using the user agent - HTTP

Browser detection using the user agent
======================================

Serving different Web pages or services to different browsers is usually a bad idea. The Web is meant to be accessible to everyone, regardless of which browser or device they're using. There are ways to develop your website to progressively enhance itself based on the availability of features rather than by targeting specific browsers.

But browsers and standards are not perfect, and there are still some edge cases where detecting the browser is needed. Using the user agent to detect the browser looks simple, but doing it well is, in fact, a very hard problem. This document will guide you in doing this as correctly as possible.

**Note:** It's worth re-iterating: it's very rarely a good idea to use user agent sniffing. You can almost always find a better, more broadly compatible way to solve your problem!

Considerations before using browser detection
---------------------------------------------

When considering using the user agent string to detect which browser is being used, your first step is to try to avoid it if possible. Start by trying to identify **why** you want to do it.

Are you trying to work around a specific bug in some version of a browser?

Look, or ask, in specialized forums: you're unlikely to be the first to hit this problem. Also, experts, or people with another point of view, can give you ideas for working around the bug. If the problem seems uncommon, it's worth checking if this bug has been reported to the browser vendor via their bug tracking system (Mozilla; WebKit; Blink; Opera). Browser makers do pay attention to bug reports, and the analysis may hint about other workarounds for the bug.

Are you trying to check for the existence of a specific feature?

Your site needs to use a specific Web feature that some browsers don't yet support, and you want to send those users to an older website with fewer features but that you know will work. This is the worst reason to use user agent detection because odds are eventually all the other browsers will catch up. In addition, it is not practical to test every one of the less popular browsers and test for those Web features. You should **never** do user agent sniffing. There is **always** the alternative of doing feature detection instead.

Do you want to provide different HTML depending on which browser is being used?

This is usually a bad practice, but there are some cases in which this is necessary. In these cases, you should first analyze your situation to be sure it's really necessary. Can you prevent it by adding some non-semantic `<div>` or `<span>` elements? The difficulty of successfully using user agent detection is worth a few disruptions to the purity of your HTML. Also, rethink your design: can you use progressive enhancement or fluid layouts to help remove the need to do this?

Avoiding user agent detection
-----------------------------

If you want to avoid using user agent detection, you have options!

Feature detection

Feature detection is where you don't try to figure out which browser is rendering your page, but instead, you check to see if the specific feature you need is available. If it's not, you use a fallback. In those rare cases where behavior differs between browsers, instead of checking the user agent string, you should instead implement a test to detect how the browser implements the API and determine how to use it from that. An example of feature detection is as follows. In 2017, Chrome unflagged experimental lookbehind support in regular expressions, but no other browser supported it. So, you might have thought to do this:

```js
// This code snippet splits a string in a special notation
let splitUpString;
if (navigator.userAgent.includes("Chrome")) {
  // YES! The user is suspected to support look-behind regexps
  // DO NOT USE /(?<=[A-Z])/. It will cause a syntax error in
  // browsers that do not support look-behind expressions
  // because all browsers parse the entire script, including
  // sections of the code that are never executed.
  const camelCaseExpression = new RegExp("(?<=[A-Z])");
  splitUpString = (str) => String(str).split(camelCaseExpression);
} else {
  // This fallback code is much less performant, but works
  splitUpString = (str) =>
    String(str)
      .split(/(.\*?[A-Z])/)
      .filter(Boolean);
}

console.log(splitUpString("fooBar")); // ["fooB", "ar"]
console.log(splitUpString("jQWhy")); // ["jQ", "W", "hy"]
```

 The above code would have made several incorrect assumptions:
 First, it assumed that all user agent strings that include the substring "Chrome" are Chrome. UA strings are notoriously misleading.
 Then, it assumed that the lookbehind feature would always be available if the browser was Chrome. The agent might be an older version of Chrome, from before support was added, or (because the feature was experimental at the time) it could be a later version of Chrome that removed it.
 Most importantly, it assumed no other browsers would support the feature. Support could have been added to other browsers at any time, but this code would have continued choosing the inferior path.

Problems like these can be avoided by testing for support of the feature itself instead:

```js
let isLookBehindSupported = false;

try {
  new RegExp("(?<=)");
  isLookBehindSupported = true;
} catch (err) {
  // If the agent doesn't support look behinds, the attempted
  // creation of a RegExp object using that syntax throws and
  // isLookBehindSupported remains false.
}

const splitUpString = isLookBehindSupported
  ? (str) => String(str).split(new RegExp("(?<=[A-Z])"))
  : (str) =>
      String(str)
        .split(/(.\*?[A-Z])/)
        .filter(Boolean);

console.log(splitUpString("fooBar")); // ["fooB", "ar"]
console.log(splitUpString("jQWhy")); // ["jQ", "W", "hy"]
```

As the above code demonstrates, there is **always** a way to test browser support without user agent sniffing. There is **never** any reason to check the user agent string for this.

Lastly, the above code snippets bring about a critical issue with cross-browser coding that must always be taken into account. Don't unintentionally use the API you are testing for in unsupported browsers. This may sound obvious and simple, but sometimes it is not. For example, in the above code snippets, using lookbehind in short-regexp notation (for example, /reg/igm) will cause a parser error in unsupported browsers. Thus, in the above example, you would use *new RegExp("(?<=look\_behind\_stuff)");* instead of */(?<=look\_behind\_stuff)/*, even in the lookbehind supported section of your code.

Progressive enhancement

This design technique involves developing your website in 'layers', using a bottom-up approach, starting with a simpler layer and improving the capabilities of the site in successive layers, each using more features.

Graceful degradation

This is a top-down approach in which you build the best possible site using all the features you want, then tweak it to make it work on older browsers. This can be harder to do, and less effective, than progressive enhancement, but may be useful in some cases.

Mobile device detection

Arguably the most common use and misuse of user agent sniffing is to detect if the device is a mobile device. However, people too often overlook what they are really after. People use user agent sniffing to detect if the users' device is touch-friendly and has a small screen so they can optimize their website accordingly. While user agent sniffing can sometimes detect these, not all devices are the same: some mobile devices have big screen sizes, some desktops have a small touchscreen, some people use smart TV's which are an entirely different ballgame altogether, and some people can dynamically change the width and height of their screen by flipping their tablet on its side! So, user agent sniffing is definitely not the way to go. Thankfully, there are much better alternatives. Use Navigator.maxTouchPoints to detect if the user's device has a touchscreen. Then, default back to checking the user agent screen only *if (!("maxTouchPoints" in navigator)) { /\*Code here\*/}*. Using this information of whether the device has a touchscreen, do not change the entire layout of the website just for touch devices: you will only create more work and maintenance for yourself. Rather, add in touch conveniences such as bigger, more easily clickable buttons (you can do this using CSS by increasing the font size). Here is an example of code that increases the padding of #exampleButton to 1em on mobile devices.

```js
let hasTouchScreen = false;
if ("maxTouchPoints" in navigator) {
  hasTouchScreen = navigator.maxTouchPoints > 0;
} else if ("msMaxTouchPoints" in navigator) {
  hasTouchScreen = navigator.msMaxTouchPoints > 0;
} else {
  const mQ = matchMedia?.("(pointer:coarse)");
  if (mQ?.media === "(pointer:coarse)") {
    hasTouchScreen = !!mQ.matches;
  } else if ("orientation" in window) {
    hasTouchScreen = true; // deprecated, but good fallback
  } else {
    // Only as a last resort, fall back to user agent sniffing
    const UA = navigator.userAgent;
    hasTouchScreen =
      /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) ||
      /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA);
  }
}

if (hasTouchScreen) {
  document.getElementById("exampleButton").style.padding = "1em";
}
```

As for the screen size, use *window.innerWidth* and window.addEventListener("resize", () => { /\*refresh screen size dependent things\*/ }). What you want to do for screen size is not slash off information on smaller screens. That will only annoy people because it will force them to use the desktop version. Rather, try to have fewer columns of information in a longer page on smaller screens while having more columns with a shorter page on larger screen sizes. This effect can be easily achieved using CSS flexboxes, sometimes with floats as a partial fallback.

Also try to move less relevant/important information down to the bottom and group the page's content together meaningfully. Although it is off-topic, perhaps the following detailed example might give you insights and ideas that persuade you to forgo user agent sniffing. Let us imagine a page composed of boxes of information; each box is about a different feline breed or canine breed. Each box has an image, an overview, and a historical fun fact. The pictures are kept to a maximum reasonable size even on large screens. For the purposes of grouping the content meaningfully, all the cat boxes are separated from all the dog boxes such that the cat and dog boxes are not intermixed together. On a large screen, it saves space to have multiple columns to reduce the space wasted to the left and to the right of the pictures. The boxes can be separated into multiple columns via two equally fair method. From this point on, we shall assume that all the dog boxes are at the top of the source code, that all the cat boxes are at the bottom of the source code, and that all these boxes have the same parent element. There a single instance of a dog box immediately above a cat box, of course. The first method uses horizontal Flexboxes to group the content such that when the page is displayed to the end user, all the dogs boxes are at the top of the page and all the cat boxes are lower on the page. The second method uses a Column layout and resents all the dogs to the left and all the cats to the right. Only in this particular scenario, it is appropriate to provide no fallback for the flexboxes/multicolumns, resulting in a single column of very wide boxes on old browsers. Also consider the following. If more people visit the webpage to see the cats, then it might be a good idea to put all the cats higher in the source code than the dogs so that more people can find what they are looking for faster on smaller screens where the content collapses down to one column.

 Next, always make your code dynamic.
 The user can flip their mobile device on its side, changing the width and height of the page.
 Or, there might be some weird flip-phone-like device thing in the future where flipping it out extends the screen.
 Do not be the developer having a headache over how to deal with the flip-phone-like device thing.
 Never be satisfied with your webpage until you can open up the dev tools side panel and resize the screen while the webpage looks smooth, fluid, and dynamically resized.
 The simplest way to do this is to separate all the code that moves content around based on screen size to a single function that is called when the page is loaded and at each resize event thereafter. If there is a lot calculated by this layout function before it determines the new layout of the page, then consider debouncing the event listener such that it is not called as often.
 Also note that there is a huge difference between the media queries `(max-width: 25em)`, `not all and (min-width: 25em)`, and `(max-width: 24.99em)`: `(max-width: 25em)` excludes `(max-width: 25em)`, whereas `not all and (min-width: 25em)` includes `(max-width: 25em)`.
 `(max-width: 24.99em)` is a poor man's version of `not all and (min-width: 25em)`: do not use `(max-width: 24.99em)` because the layout *might* break on very high font sizes on very high definition devices in the future.
 Always be very deliberate about choosing the right media query and choosing the right >=, <=, >, or < in any corresponding JavaScript because it is very easy to get these mixed up, resulting in the website looking wonky right at the screen size where the layout changes.
 Thus, thoroughly test the website at the exact widths/heights where layout changes occur to ensure that the layout changes occur properly.

Making the best of user agent sniffing
--------------------------------------

After reviewing all of the above better alternatives to user agent sniffing, there are still some potential cases where user agent sniffing is appropriate and justified.

One such case is using user agent sniffing as a fallback when detecting if the device has a touch screen. See the Mobile Device Detection section for more information.

Another such case is for fixing bugs in browsers that do not automatically update. Webkit (on iOS) is a perfect example. Apple forces all of the browsers on IOS to use Webkit internally, thus the user has no way to get a better more updated browser on older devices. Most bugs can be detected, but some bugs take more effort to detect than others. In such cases, it might be beneficial to use user agent sniffing to save on performance. For example, Webkit 6 has a bug whereby when the device orientation changes, the browser might not fire MediaQueryList listeners when it should. To overcome this bug, observe the code below.

```js
const UA = navigator.userAgent;
const isWebkit =
  /\b(iPad|iPhone|iPod)\b/.test(UA) &&
  /WebKit/.test(UA) &&
  !/Edge/.test(UA) &&
  !window.MSStream;

let mediaQueryUpdated = true;
const mqL = [];

function whenMediaChanges() {
  mediaQueryUpdated = true;
}

const listenToMediaQuery = isWebkit
  ? (mQ, f) => {
      if (/height|width/.test(mQ.media)) {
        mqL.push([mQ, f]);
      }
      mQ.addListener(f);
      mQ.addListener(whenMediaChanges);
    }
  : () => {};

const destroyMediaQuery = isWebkit
  ? (mQ) => {
      for (let i = 0; i < mqL.length; i++) {
        if (mqL[i][0] === mQ) {
          mqL.splice(i, 1);
        }
      }
      mQ.removeListener(whenMediaChanges);
    }
  : listenToMediaQuery;

let orientationChanged = false;
addEventListener(
  "orientationchange",
  () => {
    orientationChanged = true;
  },
  PASSIVE\_LISTENER\_OPTION,
);

addEventListener("resize", () =>
  setTimeout(() => {
    if (orientationChanged && !mediaQueryUpdated) {
      for (let i = 0; i < mqL.length; i++) {
        mqL[i][1](mqL[i][0]);
      }
    }
    mediaQueryUpdated = orientationChanged = false;
  }, 0),
);
```

Which part of the user agent contains the information you are looking for?
--------------------------------------------------------------------------

As there is no uniformity of the different part of the user agent string, this is the tricky part.

### Browser Name and version

When people say they want "browser detection", often they actually want "rendering engine detection". Do you actually want to detect Firefox, as opposed to SeaMonkey, or Chrome as opposed to Chromium? Or do you actually want to see if the browser is using the Gecko or the WebKit rendering engine? If this is what you need, see further down the page.

Most browsers set the name and version in the format *BrowserName/VersionNumber*. But as the name is not the only information in a user agent string that is in that format, you can not discover the name of the browser, you can only check if the name you are looking for. But note that some browsers are lying: Chrome for example reports both as Chrome and Safari. So to detect Safari you have to check for the Safari string and the absence of the Chrome string, Chromium often reports itself as Chrome too or Seamonkey sometimes reports itself as Firefox.

Also, pay attention not to use a simple regular expression on the BrowserName, user agents also contain strings outside the Keyword/Value syntax. Safari & Chrome contain the string 'like Gecko', for instance.

| Engine | Must contain | Must not contain |
| --- | --- | --- |
| Firefox | `Firefox/xyz` | `Seamonkey/xyz` |
| Seamonkey | `Seamonkey/xyz` |  |
| Chrome | `Chrome/xyz` | `Chromium/xyz` or `Edg.*/xyz` |
| Chromium | `Chromium/xyz` |  |
| Safari | `Safari/xyz` | `Chrome/xyz` or `Chromium/xyz` |
| Opera 15+ (Blink-based engine) | `OPR/xyz` |  |
| Opera 12- (Presto-based engine) | `Opera/xyz` |  |

[1] Safari gives two version numbers: one technical in the `Safari/xyz` token, and one user-friendly in a `Version/xyz` token.

Of course, there is absolutely no guarantee that another browser will not hijack some of these things (like Chrome hijacked the Safari string in the past). That's why browser detection using the user agent string is unreliable and should be done only with the check of the version number (hijacking of past versions is less likely).

### Rendering engine

As seen earlier, in most cases, looking for the rendering engine is a better way to go. This will help to not exclude lesser known browsers. Browsers sharing a common rendering engine will display a page in the same way: it is often a fair assumption that what will work in one will work in the other.

There are three active major rendering engines: Blink, Gecko, and WebKit. As sniffing the rendering engines names is common, a lot of user agents added other rendering names to trigger detection. It is therefore important to pay attention not to trigger false-positives when detecting the rendering engine.

| Engine | Must contain | Comment |
| --- | --- | --- |
| Blink | `Chrome/xyz` |  |
| Gecko | `Gecko/xyz` |  |
| WebKit | `AppleWebKit/xyz` | Pay attention, WebKit browsers add a 'like Gecko' string that may trigger false positive for Gecko if the detection is not careful. |
| Presto | `Opera/xyz` | **Note:** Presto is no longer used in Opera browser builds >= version 15 (see 'Blink') |
| EdgeHTML | `Edge/xyz` | The non-Chromium Edge puts its engine version after the *Edge/* token, not the application version. **Note:** EdgeHTML is no longer used in Edge browser builds >= version 79 (see 'Blink'). |

Rendering engine version
------------------------

Most rendering engines put the version number in the *RenderingEngine/VersionNumber* token, with the notable exception of Gecko. Gecko puts the Gecko version number in the comment part of the User Agent after the `rv:` string. From Gecko 14 for the mobile version and Gecko 17 for the desktop version, it also puts this value in the `Gecko/version` token (previous version put there the build date, then a fixed date called the GeckoTrail).

OS
--

The Operating System is given in most User Agent strings (although not web-focused platforms like Firefox OS), but the format varies a lot. It is a fixed string between two semicolons, in the comment part of the User Agent. These strings are specific for each browser. They indicate the OS, but also often its version and information on the relying hardware (32 or 64 bits, or Intel/PPC for Mac).

Like in all cases, these strings may change in the future, one should use them only in conjunction with the detection of already released browsers. A technological survey must be in place to adapt the script when new browser versions are coming out.

### Mobile, Tablet or Desktop

The most common reason to perform user agent sniffing is to determine which type of device the browser runs on. The goal is to serve different HTML to different device types.

* Never assume that a browser or a rendering engine only runs on one type of device. Especially don't make different defaults for different browsers or rendering engines.
* Never use the OS token to define if a browser is on mobile, tablet or desktop. The OS may run on more than one type of device (for example, Android runs on tablets as well as phones).

The following table summarizes the way common browser vendors indicate that their browsers are running on a mobile device:

| Browser | Rule | Example |
| --- | --- | --- |
| Mozilla (Gecko, Firefox) | `Mobile` or `Tablet` inside the comment. | `Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0` |
| WebKit-based (Android, Safari) | `Mobile Safari` token outside the comment. | `Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` |
| Blink-based (Chromium, Google Chrome, Opera 15+, Edge on Android) | `Mobile Safari` token outside the comment. | `Mozilla/5.0 (Linux; Android 4.4.2; Nexus 5 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Mobile Safari/537.36 OPR/20.0.1396.72047` |
| Presto-based (Opera 12-) | `Opera Mobi/xyz` token inside the comment. | `Opera/9.80 (Android 2.3.3; Linux; Opera Mobi/ADR-1111101157; U; es-ES) Presto/2.9.201 Version/11.50` |
| Edge on Windows 10 Mobile | `Mobile/xyz` and `Edge/` tokens outside the comment. | `Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Mobile Safari/537.36 Edge/16.16299` |

In summary, we recommend looking for the string `Mobi` anywhere in the User Agent to detect a mobile device.

**Note:** If the device is large enough that it's not marked with `Mobi`, you should serve your desktop site (which, as a best practice, should support touch input anyway, as more desktop machines are appearing with touchscreens).


HTTP resources and specifications - HTTP

HTTP resources and specifications
=================================

HTTP was first specified in the early 1990s. Designed with extensibility in mind, it has seen numerous additions over the years; this lead to its specification being scattered through numerous specification documents (in the midst of experimental abandoned extensions). This page lists relevant resources about HTTP.

| Specification | Title | Status |
| --- | --- | --- |
| RFC 9110 | HTTP Semantics | Internet Standard |
| RFC 9111 | HTTP Caching | Internet Standard |
| RFC 9112 | HTTP/1.1 | Internet Standard |
| RFC 9113 | HTTP/2 | Proposed Standard |
| RFC 9114 | HTTP/3 | Proposed Standard |
| RFC 5861 | HTTP Cache-Control Extensions for Stale Content | Informational |
| RFC 8246 | HTTP Immutable Responses | Proposed Standard |
| RFC 6265 | HTTP State Management Mechanism *Defines Cookies* | Proposed Standard |
| Draft spec | Cookie Prefixes | IETF Draft |
| Draft spec | Same-Site Cookies | IETF Draft |
| Draft spec | Deprecate modification of 'secure' cookies from non-secure origins | IETF Draft |
| RFC 2145 | Use and Interpretation of HTTP Version Numbers | Informational |
| RFC 6585 | Additional HTTP Status Codes | Proposed Standard |
| RFC 7725 | An HTTP Status Code to Report Legal Obstacles | On the standard track |
| RFC 2397 | The "data" URL scheme | Proposed Standard |
| RFC 3986 | Uniform Resource Identifier (URI): Generic Syntax | Internet Standard |
| RFC 5988 | Web Linking *Defines the `Link` header* | Proposed Standard |
| Draft spec | HTTP Client Hints | IETF Draft |
| RFC 7578 | Returning Values from Forms: multipart/form-data | Proposed Standard |
| RFC 6266 | Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP) | Proposed Standard |
| RFC 2183 | Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field *Only a subset of syntax of the `Content-Disposition` header can be used in the context of HTTP messages.* | Proposed Standard |
| RFC 7239 | Forwarded HTTP Extension | Proposed Standard |
| RFC 6455 | The WebSocket Protocol | Proposed Standard |
| RFC 5246 | The Transport Layer Security (TLS) Protocol Version 1.2 *This specification has been modified by subsequent RFCs, but these modifications have no effect on the HTTP protocol.* | Proposed Standard |
| RFC 8446 | The Transport Layer Security (TLS) Protocol Version 1.3 *Supersedes TLS 1.2.* | Proposed Standard |
| RFC 2817 | Upgrading to TLS Within HTTP/1.1 | Proposed Standard |
| RFC 7541 | HPACK: Header Compression for HTTP/2 | On the standard track |
| RFC 7838 | HTTP Alternative Services | On the standard track |
| RFC 7301 | Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension *Used to negotiate HTTP/2 at the transport to save an extra request/response round trip.* | Proposed Standard |
| RFC 6454 | The Web Origin Concept | Proposed Standard |
| Fetch | Cross-Origin Resource Sharing | Living Standard |
| RFC 7034 | HTTP Header Field X-Frame-Options | Informational |
| RFC 6797 | HTTP Strict Transport Security (HSTS) | Proposed Standard |
| Upgrade Insecure Requests | Upgrade Insecure Requests | Candidate Recommendation |
| Content Security Policy 1.0 | Content Security Policy 1.0 *CSP 1.1 and CSP 3.0 doesn't extend the HTTP standard* | Obsolete |
| Microsoft document | Specifying legacy document modes\* *Defines X-UA-Compatible* | Note |
| RFC 5689 | HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) *These extensions of the Web, as well as CardDAV and CalDAV, are out-of-scope for HTTP on the Web. Modern APIs for application are defines using the RESTful pattern nowadays.* | Proposed Standard |
| RFC 2324 | Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) | April 1st joke spec |
| RFC 7168 | The Hyper Text Coffee Pot Control Protocol for Tea Efflux Appliances (HTCPCP-TEA) | April 1st joke spec |
| HTML Living Standard | HTML *Defines extensions of HTTP for Server-Sent Events* | Living Standard |
| Reporting API | `Report-To` header | Draft |
| Draft spec | Expect-CT Extension for HTTP | IETF Draft |
| RFC 7486 | HTTP Origin-Bound Auth (HOBA) | Experimental |