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 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