---
title: Connect to RDP in a browser · Cloudflare Zero Trust docs
description: Users can connect to an RDP server without installing an RDP client
  or the WARP client on their device. Browser-based RDP leverages Cloudflare
  Tunnel, which creates a secure, outbound-only connection from your RDP server
  to Cloudflare's global network. Setup involves running the cloudflared daemon
  on the RDP server (or any other host machine within the private network) and
  routing RDP traffic over a public hostname.
lastUpdated: 2025-10-24T18:16:28.000Z
chatbotDeprioritize: false
source_url:
  html: https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/rdp/rdp-browser/
  md: https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/rdp/rdp-browser/index.md
---

Users can connect to an RDP server without installing an RDP client or the [WARP client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/warp/) on their device. Browser-based RDP leverages [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/), which creates a secure, outbound-only connection from your RDP server to Cloudflare's global network. Setup involves running the `cloudflared` daemon on the RDP server (or any other host machine within the private network) and routing RDP traffic over a public hostname.

There are two ways for users to [reach the RDP server in their browser](#4-connect-as-a-user):

* **App Launcher (recommended)**: Users can log in to the [Access App Launcher](https://developers.cloudflare.com/cloudflare-one/access-controls/access-settings/app-launcher/) with their Cloudflare Access credentials and then initiate an RDP connection within the browser to their Windows machine. Users will authenticate to the Windows machine using their pre-configured Windows username and password. Cloudflare does not manage any credentials on the Windows server.
* **Direct URL**: A user may also navigate directly to the Windows server at `https://<app-domain>/rdp/<vnet-id>/<target-ip>/<port>`, where `vnet-id` is the virtual network assigned to the Cloudflare Tunnel route. The authentication flow is the same as for the App Launcher; first users must log in to Cloudflare Access and then use their Windows credentials to authenticate to the Windows machine.

Browser-based RDP can be used in conjunction with [routing over WARP](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/use-cases/rdp/rdp-warp-to-tunnel/) so that there are multiple ways to connect to the server. You can reuse the same Cloudflare Tunnel when configuring each connection method.

## Prerequisites

* An [active domain on Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/).
* The domain uses either a [full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or a [partial (`CNAME`) setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/).
* An RDP server running a supported [Windows operating system](#rdp-server-operating-systems).

## 1. Connect the server to Cloudflare

1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Networks** > **Tunnels**.

2. [Create a new tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/) or edit an existing `cloudflared` tunnel.

1) In the **CIDR** tab for the tunnel, enter the IP or CIDR address of your server. Typically this would be a private IP, but public IPs are also allowed.

## 2. Add a target

A target represents a single resource in your infrastructure (such as a server, Kubernetes cluster, database, or container) that users will connect to through Cloudflare.

Create a target for each Windows machine that requires RDP access. To create a new target:

* Dashboard

  1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Targets**.

  2. Select **Add a target**.

  3. In **Target hostname**, enter a user-friendly name for the target. We recommend using the server hostname, for example `production-server`. The target hostname does not need to be unique and can be reused for multiple targets. Hostnames are used to define the targets secured by an Access application; they are not used for DNS address resolution.

     Hostname format restrictions

     * Case insensitive
     * Contain no more than 253 characters
     * Contain only alphanumeric characters, `-`, or `.` (no spaces allowed)
     * Start and end with an alphanumeric character

  4. In **IP addresses**, enter the IPv4 and/or IPv6 address of the target resource. The dropdown menu will not populate until you type in the full IP address.

  Note

  If the target IP does not appear in the dropdown, go to **Networks** > **Routes** and confirm that the IP routes through Cloudflare Tunnel.

  1. In the dropdown menu, select the IP address and [virtual network](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/) where the resource is located. This IP address and virtual network pairing is now assigned to this target and cannot be reused in another target by design.
  2. Select **Add target**.

* API

  Make a `POST` request to the [Infrastructure Access Targets](https://developers.cloudflare.com/api/resources/zero_trust/subresources/access/subresources/infrastructure/subresources/targets/methods/create/) endpoint:

  ```bash
  curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/infrastructure/targets" \
    --request POST \
    --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    --json '{
      "hostname": "infra-access-target",
      "ip": {
          "ipv4": {
              "ip_addr": "187.26.29.249",
              "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55"
          },
          "ipv6": {
              "ip_addr": "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0",
              "virtual_network_id": "c77b744e-acc8-428f-9257-6878c046ed55"
          }
      }
    }'
  ```

* Terraform

  Provider versions

  The following example requires Cloudflare provider version `>=4.45.0`.

  1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/api_token):

     * `Zero Trust Write`

  2. Configure the [`cloudflare_zero_trust_infrastructure_access_target`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/zero_trust_infrastructure_access_target) resource:

     ```tf
     resource "cloudflare_zero_trust_infrastructure_access_target" "infra-ssh-target" {
       account_id = var.cloudflare_account_id
         hostname   = "infra-access-target"
         ip = {
           ipv4 = {
             ip_addr = "187.26.29.249"
             virtual_network_id = "c77b744e-acc8-428f-9257-6878c046ed55"
           }
           ipv6 = {
             ip_addr = "64c0:64e8:f0b4:8dbf:7104:72b0:ec8f:f5e0"
             virtual_network_id = "c77b744e-acc8-428f-9257-6878c046ed55"
           }
         }
     }
     ```

Next, create an Access application to secure the target.

## 3. Create a DNS record

To make your RDP targets (that is, your Windows machines) available through the browser, you will need a [Cloudflare DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) for the domain and subdomain that users will connect to. This domain will be used to access any targets that are available to users through your Access application (see Step 4).

For example, if want users to connect to targets on `rdp.example.com`, [create a DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) for `rdp.example.com`. You can create either an `A`, `AAAA`, or `CNAME` record:

A record

The following DNS record points your public subdomain (`rdp`) to an IPv4 address in the [Class E address space](https://datatracker.ietf.org/doc/html/rfc5735).

* **Type**: *A*
* **Name**: `rdp`
* **IPv4 address**: `240.0.0.0`
* **Proxy status**: On

AAAA record

The following DNS record points your public subdomain (`rdp`) to the IPv6 [discard address range](https://www.rfc-editor.org/rfc/rfc6666.html):

* **Type**: *AAAA*
* **Name**: `rdp`
* **IPv6 address**: `100::`
* **Proxy status**: On

CNAME record

The following `CNAME` record points your public subdomain (`rdp`) to a fully qualified domain name.

* **Type**: *CNAME*
* **Name**: `rdp`
* **Target**: `www.rdp.example.com`
* **Proxy status**: On

The CNAME **Target** field is unrelated to the RDP targets configured in Step 2.

The DNS record does not need to point to an active destination IP address or hostname; the DNS record just needs to be valid. Cloudflare's RDP proxy will handle the routing to the correct RDP target.

## 4. Create an Access application

1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Access** > **Applications**.

2. Select **Add an application**.

3. Select **Self-hosted**.

4. Enter any name for the application.

5. In **Session Duration**, choose how often the user's [application token](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/application-token/) should expire.

   Cloudflare checks every HTTP request to your application for a valid application token. If the user's application token (and global token) has expired, they will be prompted to reauthenticate with the IdP. For more information, refer to [Session management](https://developers.cloudflare.com/cloudflare-one/access-controls/access-settings/session-management/).

1) Select **Add public hostname**.

   Note

   Browser-based RDP is only compatible with public hostnames. If you add a private hostname or IP, RDP functionality will not be available in this application.

2) In the **Domain** dropdown, select the domain that will represent the application. Domains must belong to an active zone in your Cloudflare account. You can use [wildcards](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/app-paths/) to protect multiple parts of an application that share a root path.

   Alternatively, to use a [Cloudflare for SaaS custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/secure-with-access/), set **Input method** to *Custom* and enter your custom hostname.

   Note

   You can only enable browser-based RDP on domains and subdomains, not for specific paths. The selected domain and subdomain must also have a corresponding DNS record (refer to [Step 3](#3-create-a-dns-record)).

3) Expand **Browser rendering settings**. In the **Browser rendering** dropdown, select *RDP*.

4) In **Target criteria**, select the [target hostname(s)](#2-add-a-target) that define your RDP servers. The application definition will apply to all targets that share the selected target hostname, including any targets added in the future.

5) In **Port**, enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server. It will likely be port `3389`.

6) (Optional) If you run RDP on more than one port, select **Add new target criteria** and reconfigure the same target hostname(s) with the different port number.

7) Add [Access policies](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/) to control who can connect to your application. All Access applications are deny by default -- a user must match an Allow policy before they are granted access.

Note

Ensure that only **Allow** or **Block** policies are present. **Bypass** and **Service Auth** are not supported for browser-rendered applications.

1. Configure how users will authenticate:

   1. Select the [**Identity providers**](https://developers.cloudflare.com/cloudflare-one/integrations/identity-providers/) you want to enable for your application.

   2. (Recommended) If you plan to only allow access via a single IdP, turn on **Instant Auth**. End users will not be shown the [Cloudflare Access login page](https://developers.cloudflare.com/cloudflare-one/reusable-components/custom-pages/access-login-page/). Instead, Cloudflare will redirect users directly to your SSO login event.

   3. **WARP authentication identity** is not supported for browser-based RDP and should remain turned off.

2. Select **Next**.

3. (Recommended) Turn on **Show application in App Launcher** and configure [App Launcher settings](https://developers.cloudflare.com/cloudflare-one/access-controls/access-settings/app-launcher/) for the application. The App Launcher allows users to view the Windows servers that they can access using browser-based RDP. Without the App Launcher, users will need to know each target's direct URL.

   Note

   Ensure that users match an Allow rule in your [App Launcher policies](https://developers.cloudflare.com/cloudflare-one/access-controls/access-settings/app-launcher/#enable-the-app-launcher).

4. Under **Block page**, choose what end users will see when they are denied access to the application:

   * **Cloudflare default**: Reload the [login page](https://developers.cloudflare.com/cloudflare-one/reusable-components/custom-pages/access-login-page/) and display a block message below the Cloudflare Access logo. The default message is `That account does not have access`, or you can enter a custom message.
   * **Redirect URL**: Redirect to the specified website.
   * **Custom page template**: Display a [custom block page](https://developers.cloudflare.com/cloudflare-one/reusable-components/custom-pages/access-block-page/) hosted in Zero Trust.

5. Select **Next**.

6. (Optional) Configure advanced settings:

   * [**Cross-Origin Resource Sharing (CORS) settings**](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/cors/)
   * [**Cookie settings**](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/#cookie-settings)
   * **401 Response for Service Auth policies**: Return a `401` response code when a user (or machine) makes a request to the application without the correct [service token](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/service-tokens/).

7. Select **Save**.

## 5. (Recommended) Modify order of precedence in Gateway

By default, Cloudflare will evaluate Access application policies after evaluating all Gateway network policies. To evaluate Access applications before or after specific Gateway policies:

1. Create the following [Gateway network policy](https://developers.cloudflare.com/cloudflare-one/traffic-policies/network-policies/):

   | Selector | Operator | Value | Action |
   | - | - | - | - |
   | Access Infrastructure Target | is | *Present* | Allow |

2. Ensure that **Enforce WARP client session duration** is turned off, otherwise users will be blocked from accessing RDP targets.

3. Update the policy's [order of precedence](https://developers.cloudflare.com/cloudflare-one/traffic-policies/order-of-enforcement/#order-of-precedence) using the dashboard or API.

This Gateway policy will apply to all Access for Infrastructure targets, including RDP and SSH.

Note

Users must pass the policies in your Access application before they are granted access. The Gateway Allow policy is strictly for routing and connectivity purposes.

## 6. Connect as a user

To connect to a Windows machine over RDP:

1. Open a browser and go to your App Launcher URL:

   ```text
   https://<your-team-name>.cloudflareaccess.com
   ```

   Replace `<your-team-name>` with your Zero Trust team name.

2. Follow the prompts to log in to your identity provider.

   Once you have authenticated, the App Launcher will display tiles showing the applications that you are authorized to use. Windows servers (targets) available through browser-based RDP will also appear as tiles. If a target is reachable through multiple Access applications, the target will have a tile per Access application.

3. Select the target you want to connect to.

   The App Launcher tile will launch a URL of the form `https://<app-domain>/rdp/<vnet-id>/<target-ip>/<port>`. You may also navigate directly to this URL.

   Virtual network ID

   `vnet-id` refers to the [virtual network](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/) (VNET) that the RDP target is assigned to in your Cloudflare Tunnel configuration. If you did not specify a VNET when routing the target through Cloudflare Tunnel, the target is automatically added to the default VNET.

   To fetch a list of all VNETs and their IDs, make a `GET` request to the [List Virtual Networks](https://developers.cloudflare.com/api/resources/zero_trust/subresources/networks/subresources/virtual_networks/methods/list/) endpoint. The default VNET will have the parameter `"is_default_network": true`.

4. Select the port that you want to connect to. The port selection screen only appears if the Access application allows RDP traffic on multiple ports (for example, port `3389` and port `65321`).

5. (Optional) In your browser settings, allow the Access application to access the clipboard. Clipboard permissions grant the ability to copy or paste text between the local machine and the remote Windows machine.

6. Enter your Windows username and password. For more information on how to format your username, refer to [User identifier formats](#user-identifier-formats).

You now have access to the remote Windows desktop.

## Compatibility

### RDP server operating systems

Browser-based RDP supports connecting to Windows machines that run the following operating systems:

* Windows 11 Pro
* Windows 11 Enterprise
* Windows 10 Pro
* Windows 10 Enterprise
* Windows Server 2025
* Windows Server 2022
* Windows Server 2019
* Windows Server 2016

### Browsers

| Browser | Compatibility |
| - | - |
| Google Chrome | ✅ |
| Mozilla Firefox | ✅ |
| Safari | ❌ |
| Microsoft Edge (Chromium-based) | ✅ |
| Other Chromium-based browsers (Opera, Brave) | ✅ |
| Internet Explorer 11 and below | ❌ |

### Powershell

Run Powershell 7 or higher to mitigate a prior Microsoft issue where keystrokes are not recorded.

### User identifier formats

Browser-based RDP supports connecting to Windows machines using the following login credentials:

#### Security Account Manager (SAM)

SAM-formatted user identifiers are supported with and without spaces.

Examples:

* `DOMAIN\username`
* `DOMAIN\username with spaces`
* `.\username`
* `.\username with spaces`
* `username`
* `username with spaces`

Character limits

Identifiers which specify a domain, such as `DOMAIN\username`, can have a maximum of 20 characters for the domain and 15 characters for the username.

Identifiers without a domain, such as `.\username`, will use the default domain. The username can have a maximum of 20 characters.

#### User Principal Name (UPN)

UPN-formatted user identifiers are supported with spaces, with and without quotes.

Examples:

* `"username with spaces"@domain.org`
* `username with spaces@domain.org`
* `username@domain.org`

Note

Cloudflare will not configure user identifiers on the RDP target. Any user identifier used to authenticate must be pre-configured on the server.

#### Microsoft Entra ID

User identifiers that are bound to Microsoft Entra ID domains must enter their username as `AzureAD\user@example.com` or `AzureAD\user`. The `AzureAD\` prefix is case-insensitive. The login flow differs slightly when using an Microsoft Entra ID-bound username:

1. Enter your username in one of the formats outlined above.
2. Once the username is entered, the password box will disappear and the RDP connection will initiate.
3. The RDP server will then prompt for the password before granting access to the RDP server.

### Cloudflare products

When using Access self-hosted applications, the majority of Cloudflare products will be compatible with your application.

However, the following products are not supported:

* [Automatic Platform Optimization](https://developers.cloudflare.com/automatic-platform-optimization)
* [Zaraz](https://developers.cloudflare.com/zaraz)

You can disable Zaraz for a specific application - instead of across your entire zone - using a [Configuration Rule](https://developers.cloudflare.com/rules/configuration-rules/) scoped to the application domain.

## Known limitations

* **TLS certificate verification**: Cloudflare uses TLS to connect to the RDP target but does not verify the origin TLS certificate.
* **WARP authentication**: Since browser-based RDP traffic does not go through the WARP client, users cannot use their [WARP session identity](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/warp/configure-warp/warp-sessions/#configure-warp-sessions-in-access) to authenticate.
* **Audio over RDP**: Users cannot use their microphone and speaker to interact with the remote machine.
* **Clipboard size limit**: Data copied between the local machine and the browser-based RDP session may not exceed 500 KB.
* **Clipboard controls**: Admins do not have the ability to restrict copy/paste actions between the remote machine and the user's local clipboard.
* **File transfers**: Users cannot copy/paste files from their local machine to the remote machine and vice versa.
* **Print to local printer**: Users cannot print information from their browser-based RDP session to a printer in their local network.
* **Network Level Authentication for Entra-joined accounts**: Browser-based RDP does not support PKU2U authentication which is required for [Network Level Authentication (NLA)](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remotepc/remote-desktop-allow-access#why-allow-connections-only-with-network-level-authentication) with Entra-joined accounts. Connecting to Entra-joined accounts requires disabling enforcement of NLA on the remote Windows machine. You can disable NLA from **Settings** > **System** > **Remote Desktop**, or use the Local Group Policy Editor to disable **Require user authentication for remote connections by using Network Level Authentication**.
