19
19
19
Disable Access Policy in Cloudflare Pages

Disable Access Policy in Cloudflare Pages

298
April 20, 2025
4 min read
Table of Contents

What is this about?

For those who don’t know what Access Policy is in Cloudflare Pages, it’s a feature that allows you to restrict access to your preview deployments.

I’m not here talk about if this feature is useful or not. The actual problem is, you can enable this feature while being in the free plan, but you can’t disable it without upgrading to a paid plan. Like “What the hell?” -.-

As of today, there is no straight forward way to disable the access policy without upgrading to a paid plan. But there’s a workaround. You can use Cloudflare’s API to disable the access policy for your project.

So, instead of jumping between documentation and the Cloudflare dashboard, you can just follow the steps below to disable the access policy in Cloudflare Pages.

If you want to see a step-by-step video guide, watch this video:

youtu.be/qqQ_UaPCTFY

If you’re a beginner, I strongly recommend that you watch the video.

Steps to disable Access Policy in Cloudflare Pages

There are two thing you’ll need for this:

  1. Your Account ID.
  2. An API token with the Account Access permission.

How to get your account ID

Go to the Cloudflare dashboard. Look at the URL. It should look something like this:

dash

Your account id will look like this: 6a2784243169ac723308b65ae743e5ca

Our first step is done.

How to get the API token?

  • Go to the API Tokens page.
  • Click on Create Token
  • Go to the bottom and go with Create Custom Token and do these steps
    • Token Name: Give any name
    • Permissions: Account -> Access: Apps and Policies -> Edit
    • Account Resources: Include -> All Accounts ( default )
    • Client IP Address Filtering: Is Not In -> 192.168.0.1 (any ip other than yours)
    • TTL: Leave it empty

Then continue. Copy the API Token. Remember to not expose this token anywhere.

We now have everything we need. We’ll just need to run two curl commands to disable the access policy.

Commands

Run the following commands in your terminal (not powershell). If you do not replace the <VARIABLE> with the proper instruction, you’ll get an error like this:

curl: (3) URL rejected: Malformed input to a URL function

Get the list of apps with Access Policy enabled

Replace <ACCOUNT ID> with your account id and <API TOKEN> with the token you just created.

curl -X GET "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT ID>/access/apps" -H "Authorization: Bearer <API TOKEN>" -H "Content-Type: application/json"

You’ll get a response like this:

{
  "result": [
    {
      "id": "55061f3f-83e3-43d2-8ac2-47d78fa7e192",
      "uid": "55061f3f-83e3-43d2-8ac2-47d78fa7e192",
      "type": "self_hosted",
      "name": "hellofromtheotherside - Cloudflare Pages",
      "aud": "5fac07900aaf8778308a6469db5b76969e08b6e4757df404eac6a47b7d5aea9c",
      "created_at": "2025-04-20T04:45:33Z",
      "updated_at": "2025-04-20T04:45:33Z",
      "domain": "*.hellofromtheotherside.pages.dev",
      "self_hosted_domains": ["*.hellofromtheotherside.pages.dev"],
      "destinations": [
        {
          "type": "public",
          "uri": "*.hellofromtheotherside.pages.dev"
        }
      ],
      "app_launcher_visible": true,
      "allowed_idps": ["f4811179-450b-448f-8ae8-fb3bc0ed0ce8"],
      "tags": [],
      "auto_redirect_to_identity": false,
      "policies": [
        {
          "created_at": "2025-04-20T04:45:33Z",
          "decision": "allow",
          "exclude": [],
          "id": "6d63abdb-1cfd-4882-bf67-9d8eb4c2a1b4",
          "include": [
            {
              "email": {
                "email": "nusabtaha33@gmail.com"
              }
            }
          ],
          "name": "Allow Members - Cloudflare Pages",
          "require": [],
          "uid": "6d63abdb-1cfd-4882-bf67-9d8eb4c2a1b4",
          "updated_at": "2025-04-20T04:45:33Z",
          "reusable": false,
          "precedence": 1
        }
      ],
      "session_duration": "24h",
      "enable_binding_cookie": false,
      "http_only_cookie_attribute": true,
      "options_preflight_bypass": false
    }
  ],
  "success": true,
  "errors": [],
  "messages": [],
  "result_info": {
    "page": 1,
    "per_page": 1000,
    "count": 1,
    "total_count": 1,
    "total_pages": 1
  }
}

From the result, copy the uid of the app. Now run the following command where <APP UID> is the uid you just copied.

curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT ID>/access/apps/<APP UID>" -H "Authorization: Bearer <API TOKEN>" -H "Content-Type: application/json"

And you’re done! The access policy should be disabled if you’ve done everything correctly.

Python code to automate the process

Here is a python script that you can use to do the task for you. You just need to update the ACCOUNT_ID and API_TOKEN variable. It basically does the same thing. Just without the hassle of manually copying and pasting the app’s uid.

You can find the code in this gist too.

#!/usr/bin/env python3
import requests
import sys
 
# Configure these variables with your actual Cloudflare account details
ACCOUNT_ID = "your_account_id_here" # eg. "6a2784243169ac723308b65ae743e5ca"
API_TOKEN = "your_api_token_here" # eg. "a-FJVHPa04_9TS0L5RjYIcTgtLfc8NwP9PNqyd6m"
 
def main():
    # Check if credentials are set
    if ACCOUNT_ID == "your_account_id_here" or API_TOKEN == "your_api_token_here":
        print("ERROR: Please update the ACCOUNT_ID and API_TOKEN variables with your actual credentials.")
        sys.exit(1)
 
    # Common headers for all requests
    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json"
    }
 
    # Get all access apps
    print(f"Fetching Access apps for account: {ACCOUNT_ID}...")
    url = f"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/access/apps"
 
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        data = response.json()
 
        if not data["success"]:
            print(f"ERROR: API request failed with errors: {data['errors']}")
            sys.exit(1)
 
        apps = data["result"]
        print(f"Found {len(apps)} Access app(s).")
 
        # Delete each app
        for app in apps:
            app_uid = app["uid"]
            app_name = app["name"]
 
            print(f"Deleting Access app: {app_name} (UID: {app_uid})...")
            delete_url = f"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/access/apps/{app_uid}"
 
            delete_response = requests.delete(delete_url, headers=headers)
            delete_data = delete_response.json()
 
            if delete_data["success"]:
                print(f"✓ Successfully deleted '{app_name}'")
            else:
                print(f"✗ Failed to delete '{app_name}': {delete_data['errors']}")
 
        print("\nDeletion process complete.")
 
    except requests.exceptions.RequestException as e:
        print(f"ERROR: Request failed: {e}")
        sys.exit(1)
 
if __name__ == "__main__":
    main()


So…

When I faced this issue, I didn’t find a straightforward way from the docs. After digging through some of the community posts, I found this answer.

Thanks to him.

The main reason for writing this blog is so others don’t need to do all the hassle, especially for beginners.

Peace!