Sunday, February 16, 2025
No menu items!
HomeData Analytics and VisualizationCloudflare : How to Get Unique Visitors Data

Cloudflare : How to Get Unique Visitors Data

This tutorial explains how to fetch unique visitors data from cloudflare.

Cloudflare allows you to download unique visitor data after logging into the dashboard. However it lacks flexibility in specifying date ranges and is not efficient for automation or further analysis.

Cloudflare gives an option to download various data points via GraphQL queries using its API. You need to have API key, email and zone id to use API.

Instructions : You can find your API key in the Cloudflare dashboard by clicking on profile icon (top-right) > My Profile > API Tokens. Either you can use global API key or you can create a custom API token with specific permissions. The Zone ID is available on the Overview page of your site in Cloudflare.

The following Python code returns the total unique visitors to your site in the past 24 hours along with unique visitors per hour.

import requests
import json
import pandas as pd
from datetime import datetime, timedelta
from tzlocal import get_localzone
local_timezone = get_localzone()

# Define date range (Past 24 hours)
now = datetime.utcnow().replace(minute=0, second=0, microsecond=0)
start_date = now - timedelta(days=1)
end_date = now

# ISO Format
start_date_str = start_date.strftime("%Y-%m-%dT%H:%M:%SZ")
end_date_str = end_date.strftime("%Y-%m-%dT%H:%M:%SZ")

# Cloudflare API credentials
API_KEY = "xxxxxxxxxxx"
ZONE_ID = "xxxxxxxxx"
API_EMAIL = "[email protected]"

# Set up headers
headers = {
    "X-Auth-Email": API_EMAIL,
    "X-Auth-Key": API_KEY,
    "Content-Type": "application/json"
}

# GraphQL query with date range filter
query = """
query GetZoneAnalytics($zoneTag: String!, $datetime_geq: DateTime!, $datetime_lt: DateTime!) {
  viewer {
    zones(filter: { zoneTag: $zoneTag }) {
      totals: httpRequests1hGroups(limit: 10000, filter: { datetime_geq: $datetime_geq, datetime_lt: $datetime_lt }) {
        uniq {
          uniques
        }
      }
      zones: httpRequests1hGroups(orderBy: [datetime_ASC], limit: 10000, filter: { datetime_geq: $datetime_geq, datetime_lt: $datetime_lt }) {
        dimensions {
          timeslot: datetime
        }
        uniq {
          uniques
        }
      }
    }
  }
}
"""

# Create request body
payload = {
    "query": query,
    "variables": {
        "zoneTag": ZONE_ID,
        "datetime_geq": start_date_str,
        "datetime_lt": end_date_str
    }
}

# Make API request
response = requests.post(
    url="https://api.cloudflare.com/client/v4/graphql",
    headers=headers,
    json=payload
)

# Process response
if response.status_code > 200:
    raise Exception(f"Error: {response.status_code}, {response.text}")

data = response.json()

# Print full JSON response (optional)
print(json.dumps(data, indent=4))

# Extract data safely
try:
    # Try accessing both totals and zones data from the response
    zones_data = data.get('data', {}).get('viewer', {}).get('zones', [{}])[0]
    
    # Extract totals and zone data, ensuring the keys exist
    totals = zones_data.get('totals', [])
    http_requests = zones_data.get('zones', [])
    
    # Calculate total unique visits
    total_uniques = sum(group.get('uniq', {}).get('uniques', 0) for group in totals)

    # Create list of records for DataFrame
    records = []
    for entry in http_requests:
        timeslot = entry.get("dimensions", {}).get("timeslot", "N/A")
        uniques = entry.get("uniq", {}).get("uniques", 0)
        records.append({"datetime": timeslot, "Unique Visits": uniques})

    # Convert to DataFrame
    df = pd.DataFrame(records)
    df['datetime'] = pd.to_datetime(df['datetime']).dt.tz_localize(None)
    df['datetime'] = df['datetime'].dt.tz_localize('UTC').dt.tz_convert(local_timezone).dt.tz_localize(None)
    df = df.sort_values(by='datetime', ascending=False)

    # Append total row
    total_row = pd.DataFrame([{"datetime": "Total", "Unique Visits": total_uniques}])
    df = pd.concat([df, total_row], ignore_index=True)

    # Save to Excel
    output_file = "cloudflare_analytics.xlsx"
    df.to_excel(output_file, index=False)

    # Print total
    print(f"nTotal Unique Visits from {start_date} to {end_date}: {total_uniques}")
    print(f"Data saved to {output_file}")

except (TypeError, IndexError, KeyError) as e:
    print(f"Error processing data: {e}")

The code above creates a pandas dataframe named df and store data in it. Then it writes the dataframe to an excel file in your working directory.

Unique Visitors Data From Cloudflare

Unique Visitors by Day

The following Python code returns the total unique visitors to your site in the past 7 days along with unique visitors per day.

import requests
import json
import pandas as pd
from datetime import datetime, timedelta
from tzlocal import get_localzone
local_timezone = get_localzone()

# Define date range (Past 7 days)
now = datetime.utcnow().replace(minute=0, second=0, microsecond=0)
start_date = now - timedelta(days=7)
end_date = now

# ISO Format
start_date_str = start_date.strftime("%Y-%m-%d")
end_date_str = end_date.strftime("%Y-%m-%d")

# Cloudflare API credentials
API_KEY = "xxxxxxxxxxx"
ZONE_ID = "xxxxxxxxxxxxxx"
API_EMAIL = "[email protected]"

# Set up headers
headers = {
    "X-Auth-Email": API_EMAIL,
    "X-Auth-Key": API_KEY,
    "Content-Type": "application/json"
}

# GraphQL query with date range filter
query = """
query GetZoneAnalytics($zoneTag: string, $date_geq: string, $date_lt: string) {
  viewer {
    zones(filter: { zoneTag: $zoneTag }) {
      totals: httpRequests1dGroups(limit: 10000, filter: { date_geq: $date_geq, date_lt: $date_lt }) {
        uniq {
          uniques
        }
      }
      zones: httpRequests1dGroups(orderBy: [date_ASC], limit: 10000, filter: { date_geq: $date_geq, date_lt: $date_lt }) {
        dimensions {
          timeslot: date
        }
        uniq {
          uniques
        }
      }
    }
  }
}
"""

# Create request body
payload = {
    "query": query,
    "variables": {
        "zoneTag": ZONE_ID,
        "date_geq": start_date_str,
        "date_lt": end_date_str
    }
}

# Make API request
response = requests.post(
    url="https://api.cloudflare.com/client/v4/graphql",
    headers=headers,
    json=payload
)

# Process response
if response.status_code > 200:
    raise Exception(f"Error: {response.status_code}, {response.text}")

data = response.json()

# Print full JSON response (optional)
print(json.dumps(data, indent=4))

# Extract data safely
try:
    # Try accessing both totals and zones data from the response
    zones_data = data.get('data', {}).get('viewer', {}).get('zones', [{}])[0]
    
    # Extract totals and zone data, ensuring the keys exist
    totals = zones_data.get('totals', [])
    http_requests = zones_data.get('zones', [])
    
    # Calculate total unique visits
    total_uniques = sum(group.get('uniq', {}).get('uniques', 0) for group in totals)

    # Create list of records for DataFrame
    records = []
    for entry in http_requests:
        timeslot = entry.get("dimensions", {}).get("timeslot", "N/A")
        uniques = entry.get("uniq", {}).get("uniques", 0)
        records.append({"Date": timeslot, "Unique Visits": uniques})

    # Convert to DataFrame
    df = pd.DataFrame(records)

    # Append total row
    total_row = pd.DataFrame([{"Date": "Total", "Unique Visits": total_uniques}])
    df = pd.concat([df, total_row], ignore_index=True)

    # Save to Excel
    output_file = "cloudflare_analytics2.xlsx"
    df.to_excel(output_file, index=False)

    # Print total
    print(f"nTotal Unique Visits from {start_date} to {end_date}: {total_uniques}")
    print(f"Data saved to {output_file}")

except (TypeError, IndexError, KeyError) as e:
    print(f"Error processing data: {e}")

Read MoreListenData

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments