---
title: DNS over HTTPS (DoH) · Cloudflare Zero Trust docs
description: With Cloudflare Gateway, you can filter DNS over HTTPS (DoH)
  requests by DNS location or by user without needing to install the WARP client
  on your devices.
lastUpdated: 2025-10-24T20:47:24.000Z
chatbotDeprioritize: false
source_url:
  html: https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/agentless/dns/dns-over-https/
  md: https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/agentless/dns/dns-over-https/index.md
---

With Cloudflare Gateway, you can filter DNS over HTTPS (DoH) requests by [DNS location](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/agentless/dns/locations/) or by user without needing to install the WARP client on your devices.

Location-based policies require that you send DNS requests to a [location-specific DoH endpoint](#filter-doh-requests-by-location), while identity-based policies require that requests include a [user-specific DoH token](#filter-doh-requests-by-user).

## Filter DoH requests by location

Location-based policies require that you send DNS queries to a unique DoH endpoint assigned to the location:

```txt
https://<YOUR_DOH_SUBDOMAIN>.cloudflare-gateway.com/dns-query
```

### Prerequisites

Obtain your location's DoH subdomain.

### Configure browser for DoH

Browsers can be configured to use any DNS over HTTPS (DoH) endpoint. If you choose to configure DoH directly in your browser, you must choose a Gateway DNS location as your DoH endpoint, otherwise DNS filtering will not occur in that browser.

Mozilla Firefox

1. In Firefox, go to **Settings**.
2. In **Privacy & Security**, go to **DNS over HTTPS**.
3. Under **Enable secure DNS using**, select *Max Protection*.
4. In **Choose provider**, choose *Custom*.
5. In the field, enter `https://<YOUR_DOH_SUBDOMAIN>.cloudflare-gateway.com/dns-query`.

Firefox is now configured to use your DoH endpoint. For more information on configuring DoH settings in Firefox, refer to [Mozilla's documentation](https://support.mozilla.org/kb/dns-over-https).

Note

If you want to enforce DNS policies through WARP instead of over DoH, you can disable DoH for your organization by blocking the [Firefox DoH canary domain](https://support.mozilla.org/kb/canary-domain-use-application-dnsnet).

Google Chrome

1. In Chrome, go to **Settings** > **Privacy and security** > **Security**.
2. Scroll down and turn on **Use secure DNS**.
3. Select **With Custom**.
4. In the **Enter custom provider** field, enter `https://<YOUR_DOH_SUBDOMAIN>.cloudflare-gateway.com/dns-query`.

Read more about [enabling DNS over HTTPS](https://www.chromium.org/developers/dns-over-https) on Chrome.

Microsoft Edge

1. In Microsoft Edge, go to **Settings**.
2. Select **Privacy, Search, and Services**, and scroll down to **Security**.
3. Turn on **Use secure DNS**.
4. Select **Choose a service provider**.
5. In the **Enter custom provider** field, enter `https://<YOUR_DOH_SUBDOMAIN>.cloudflare-gateway.com/dns-query`.

Brave

1. In Brave, go to **Settings** > **Security and Privacy** > **Security**.
2. Turn on **Use secure DNS**.
3. Select **With Custom**.
4. In the **Enter custom provider** field, enter `https://<YOUR_DOH_SUBDOMAIN>.cloudflare-gateway.com/dns-query`.

Safari

Currently, Safari does not support DNS over HTTPS.

Your DNS queries will now be sent to Gateway for filtering. To filter these requests, build a DNS policy using the [**DNS Location**](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/agentless/dns/locations/) selector.

### Configure operating system for DoH

Windows 11

1. Obtain the `A` and `AAAA` record values associated with your location's DoH endpoint.

   1. Run the following command to obtain your `A` record values:

   ```powershell
   nslookup -type=A <your-subdomain>.cloudflare-gateway.com
   ```

   1. Obtain your `AAAA` record values.

   ```powershell
   nslookup -type=AAAA <your-subdomain>.cloudflare-gateway.com
   ```

   1. Copy the resulting IP addresses.

2. Add the addresses to your list of known DoH servers.

   1. Run the following command for each address:

   ```powershell
   Add-DnsClientDohServerAddress -ServerAddress <IP-address> -DohTemplate https://<your-subdomain>.cloudflare-gateway.com/dns-query -AllowFallbackToUdp $False -AutoUpgrade $False
   ```

   1. Confirm the addresses were added.

   ```powershell
   Get-DnsClientDohServerAddress
   ```

3. In Windows, go to **Settings** > **Network & internet** > your active Internet connection. This option may be either **Ethernet** or **Wi-Fi**.

4. Under **DNS server assignment**, select **Edit**.

5. In the drop-down menu, choose *Manual*.

6. Enable **IPv4**.

7. In **Preferred DNS** and **Alternate DNS**, enter the IPv4 addresses from your `A` record command. Set **DNS over HTTPS** to *On (automatic template)*.

8. Enable **IPv6**.

9. In **Preferred DNS** and **Alternate DNS**, enter the IPv6 addresses from your `AAAA` record command. Set **DNS over HTTPS** to *On (automatic template)*.

Windows Server 2022

Obtain the `A` and `AAAA` record values associated with your location's DoH endpoint.

1. Run the following command to obtain your `A` record values:

```powershell
nslookup -type=A <your-subdomain>.cloudflare-gateway.com
```

1. Obtain your `AAAA` record values.

```powershell
nslookup -type=AAAA <your-subdomain>.cloudflare-gateway.com
```

1. Copy the resulting IP addresses.
2. [Add the addresses](https://learn.microsoft.com/en-us/windows-server/networking/dns/doh-client-support#add-a-new-doh-server-to-the-list-of-known-servers) to your list of known DoH servers.
3. [Configure the Windows Server client](https://learn.microsoft.com/en-us/windows-server/networking/dns/doh-client-support#configure-the-dns-client-to-support-doh) or [set up a Group Policy](https://learn.microsoft.com/en-us/windows-server/networking/dns/doh-client-support#configuring-doh-through-group-policy) to use DoH.

For more information, refer to [Microsoft's DoH guide](https://learn.microsoft.com/en-us/windows-server/networking/dns/doh-client-support) for Windows Server 2022 and newer.

### Use generic DoH endpoint

You can send DoH requests to the generic Cloudflare DoH endpoint, `dns.cloudflare-gateway.com`. To specify a location in your request, include a header named `cf-dns-location` with a value of your location's DoH subdomain. For example:

```http
GET /dns-query?name=example.com&type=A HTTP/2
Host: dns.cloudflare-gateway.com
cf-dns-location: 9y65g5srsm
Accept: application/dns-message
```

## Filter DoH requests by user

In order to filter DoH queries based on user identity, each query must include a user-specific authentication token. If you have several devices per user and want to apply device-specific policies, you will need to map each device to a different email.

Currently, authentication tokens can only be generated through the API. You can run this [interactive Python script](https://developers.cloudflare.com/cloudflare-one/static/authenticated-doh.py) which automates the setup procedure, or follow the steps described below.

### 1. Create a service token for the account

Each Cloudflare account can only have one active Access [service token](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/service-tokens/) authorized for DNS over HTTPS (DoH) at a time.

```bash
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/service_tokens" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{"name":"ACME Corporation service token"}'
```

Save the service token's `client_id`, `client_secret`, and `id`.

Example response

```json
{
  "result": {
    "client_id": "88bf3b6d86161464f6509f7219099e57.access",
    "client_secret": "bdd31cbc4dec990953e39163fbbb194c93313ca9f0a6e420346af9d326b1d2a5",
    "created_at": "2022-06-09T01:59:17Z",
    "expires_at": "2023-06-09T01:59:17Z",
    "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
    "name": "ACME Corporation service token",
    "updated_at": "2022-06-09T01:59:17Z"
  },
  "success": true,
  "errors": [],
  "messages": []
}
```

### 2. Enable DoH functionality for the service token

```bash
curl --request PUT \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations/doh/$SERVICE_TOKEN_ID" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

If you get an `access.api.error.service_token_not_found` error, check that `$SERVICE_TOKEN_ID` is the value of `id` and not `client_id`.

Note

Although you can create multiple valid service tokens, only one service token can be designated for issuing DoH tokens. Calling the API to enable DoH on a new service token replaces the previously active service token. If a new token overrides an active service token, the API call will fail.

Example response

```json
{
  "result": {
    "client_id": "88bf3b6d86161464f6509f7219099e57.access",
    "created_at": "2022-06-09T01:59:17Z",
    "expires_at": "2023-06-09T01:59:17Z",
    "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
    "name": "ACME Corporation service token",
    "updated_at": "2022-06-09T01:59:17Z",
    "duration": "8760h"
  },
  "success": true,
  "errors": [],
  "messages": []
}
```

### 3. Create a user

Create a new user and optionally add them to a group.

```bash
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/users" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
  "name": "John Doe",
  "email": "jdoe@acme.com",
  "custom": {"groups":[{"id": "02fk6b3p3majl10", "email": "finance@acme.com", "name": "Finance"}]}
}'
```

Save the user's `id` returned in the response.

Example response

```json
{
  "result": {
    "id": "54d425de-7a78-4186-9975-d43c88ee7899",
    "created_at": "2022-03-16T21:18:39.93598Z",
    "updated_at": "2022-05-17T23:50:39.598345Z",
    "uid": "54d425de-7a78-4186-9975-d43c88ee7899",
    "name": "John Doe",
    "email": "jdoe@acme.com",
    "custom": {
      "groups": [
        {
          "email": "finance@acme.com",
          "id": "02fk6b3p3majl10",
          "name": "Finance"
        }
      ]
    }
  },
  "success": true,
  "errors": [],
  "messages": []
}
```

Note

Steps 1-3 above only need to be completed once, while Steps 4-5 below would occur during normal operation.

### 4. Generate a DoH token for the user

Request a DoH token for the user, using your service token to authenticate into your team domain.

```bash
curl "https://<TEAM_NAME>.cloudflareaccess.com/cdn-cgi/access/doh-token?account-id=<ACCOUNT_ID>&user-id=<USER_ID>&auth-domain=<TEAM_NAME>.cloudflareaccess.com" \
--header "Cf-Access-Client-Id: <CLIENT_ID>" \
--header "Cf-Access-Client-Secret: <CLIENT_SECRET>"
```

The response contains a unique DoH token associated with the user. This token expires in 24 hours. We recommend setting up a refresh flow for the DoH token instead of generating a new one for every DoH query.

Example response

```json
{
  "token": "y2khbGciOiJSUzI1NiIsImtpZCI6ImJlZjVkYjg4ZTEwMjk3ZDEwNzhkMmEyYjE0MjMxZTljYTQwMjQ2NjAwOTQzNmJhOTQwOGJkODY3ZmI4OWFiOGQifQ.eyJ0eXBlIjoiZG9oIiwiYXVkIjoiY2xvdWRmbGFyZS1nYXRld2F5LmNvbSIsImlhdCI6MTY1NDc1MTg3NSwiZXhwIjoxNjU0ODM4Mjc1LCJhY2NvdW50LWlkIjoiMTA4MDM0OGIyZGYzYmQwN2QxZmI1MjM3Y2Q1ZDU5M2EiLCJ1c2VyLWlkIjoiNTRkNDI1ZGUtN2E3OC00MTg2LTk5NzUtZDQzYzg4ZWU3ODk5In0.I5p4WsH2dPhQ8vwy84zF05PsoBHCsUSXAaMpNhEH36oFZ3tXcs9ksLz7OzpZ_x3HxUfO3n57LlpAF1VehaBt2i94XCkvSgtHpYcwd_qZydLp-BGtcyfU1LbdXQC3m6zxKcIWu5VySi8I-J25UYlpyJhYgZ4DQUZIpqbSSt6WcVRKvA7OBa7xjkTux4OcqWAViO_ZS-GLwl-fqhvolmiwk37seBD3YuV1zG06VeWXfrMkZ5MbhooHD1DZDBHOZpTtmN8MbeKeI4tlY1mb_O3-jE-um6F9Hrl4NQm89MKFzsum-_Rywi5m4PTSlDza7fjdJs7RzFgJd3VWgzG-jgyQKw"
}
```

### 5. Send an authenticated DoH query

Send DoH queries to the resolver at `https://<ACCOUNT_ID>.cloudflare-gateway.com/dns-query`, making sure to include the user's DoH token in the `CF-Authorization` header.

```bash
curl --silent "https://<ACCOUNT_ID>.cloudflare-gateway.com/dns-query?name=example.com" \
--header "accept: application/dns-json" \
--header "CF-Authorization: <USER_DOH_TOKEN>" | jq
```

If the site is blocked and you have turned on the [block page](https://developers.cloudflare.com/cloudflare-one/traffic-policies/block-page/#configure-policy-block-behavior) for the policy, the query will return `162.159.36.12` (the IP address of the Gateway block page). If the block page is disabled, the response will be `0.0.0.0`.

Example response

```json
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "example.com",
      "type": 1
    }
  ],
  "Answer": [
    {
      "name": "example.com",
      "type": 1,
      "TTL": 60,
      "data": "162.159.36.12"
    }
  ]
}
```

You can verify that the request was associated with the correct user email by checking your [Gateway DNS logs](https://developers.cloudflare.com/cloudflare-one/insights/logs/gateway-logs/). To filter these requests, build a DNS policy using any of the Gateway [identity-based selectors](https://developers.cloudflare.com/cloudflare-one/traffic-policies/identity-selectors/).
