How to extract server access logs from a Squarespace website

You read that title correctly. You can do some form of server log file analysis on a Squarespace website, even though you cannot readily find the logs. Surprised?

How this post came to be and the limitations of Squarespace Activity Logs

You might be asking “Why would someone want to perform a server log file analysis on a Squarespace website?” Easy – I have a client on Squarespace, and I wanted to know if it is possible to see the crawlbot records.

I knew Squarespace had something like these in an interface, but they were always opaque and inaccessible.

Undeterred and highly curious, I crafted an in-browser script that will open and load each entry, then scrape it and add it to a CSV file, then created a Google Colab script in Python to match the known crawlbot IP addresses with the reported ones.

Ultimately, I discovered Squarespace does not log crawl entries, so my work was ultimately fruitless for discerning AI crawlers. However, if you want to store, process, and analyze real user activity, you may find this useful.

How to Squarespace Server Access Logs from the Activity Log

Logs are available in the Analytics interface (/config/analytics#activity-log). The interface initially loads 50. To load more, you will need to click the button Load More at the bottom of the interface, scroll, and repeat until you have loaded as many entries as you deem sufficient. You should also know that the interface holds a maximum 7 days’ worth of data from your current moment in time.

Note: I tried to automate clicking Load More using Javascript in the browser interface, but was not able to do so.

After you have loaded as many entries as you care to extract, open your browser’s developer tools and go to the console.

Paste the following script below and hit enter. Then wait until it finishes and exports a CSV.

(async () => {
    console.log("🚀 Starting clean extraction...");

    const rows = Array.from(document.querySelectorAll('button.css-1dtyuja'));
    const results = [];

    for (const [index, btn] of rows.entries()) {
        if (btn.getAttribute('aria-expanded') !== 'true') {
            btn.click();
            await new Promise(r => setTimeout(r, 600)); 
        }

        const region = btn.nextElementSibling;
        const headerPs = btn.querySelectorAll('p');

        // Helper: Extracts value and removes the label (e.g., "Location: United States" -> "United States")
        const getCleanVal = (label) => {
            const el = Array.from(region.querySelectorAll('li'))
                            .find(li => li.innerText.includes(label));
            if (!el) return "";
            // If the value is in the next sibling (common in this HTML), grab that.
            // Otherwise, strip the label text from the current element.
            const val = el.nextElementSibling ? el.nextElementSibling.innerText : el.innerText.replace(label, "");
            return val.trim();
        };

        // Specific User Agent logic: It's the long string containing "Mozilla"
        const userAgent = Array.from(region.querySelectorAll('li'))
                               .find(li => li.innerText.includes('Mozilla/'))?.innerText.trim() || "";

        results.push({
            "Timestamp": headerPs[0]?.innerText.trim() || "",
            "IP_Address": headerPs[1]?.innerText.trim() || "",
            "Item": headerPs[2]?.innerText.trim() || "",
            "Location": getCleanVal("Location:"),
            "Referrer": getCleanVal("Referrer:"),
            "User_Agent": userAgent
        });

        console.log(`✅ Cleaned row ${index + 1}`);
    }

    // --- CSV GENERATION (Excel-Safe) ---
    const headers = Object.keys(results[0]);
    
    // Wrap every value in double quotes and escape existing quotes
    const csvContent = [
        headers.join(","), 
        ...results.map(row => 
            headers.map(fieldName => {
                const value = String(row[fieldName] || "").replace(/"/g, '""'); // Escape double quotes
                return `"${value}"`; 
            }).join(",")
        )
    ].join("\n");

    // Download
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.setAttribute("href", url);
    link.setAttribute("download", `clean_data_${new Date().toISOString().slice(0,10)}.csv`);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    console.log("✨ Clean CSV ready!");
})();

That’s it. You can now store and perform an analysis of your entries.

How to validate common search and generative AI crawlbots IP addresses

If you want to double-check your own logs for AI crawlbot entries in Python or Google Colab, you can repurpose the code block below.

import csv
import ipaddress

# Official IP ranges (Example subsets - add your full list here)
BOT_RANGES = {
    "ChatGPT-User": [
        "104.210.139.192/28", "104.210.139.224/28", "13.65.138.112/28", "13.65.138.96/28", "13.67.46.240/28", "13.67.72.16/28", "13.70.107.160/28", "13.71.2.208/28", "13.76.115.224/28", "13.76.115.240/28", "13.76.116.80/28", "13.76.223.48/28", "13.76.32.208/28", "13.79.43.0/28", "13.83.167.128/28", "13.83.237.176/28", "132.196.82.48/28", "135.119.134.128/28", "135.119.134.192/28", "135.220.73.208/28", "135.220.73.240/28", "135.237.131.208/28", "135.237.133.112/28", "135.237.133.48/28", "137.135.183.96/28", "137.135.190.240/28", "137.135.191.176/28", "137.135.191.32/28", "138.91.30.48/28", "138.91.46.96/28", "168.63.252.240/28", "172.178.140.144/28", "172.178.141.112/28", "172.178.141.128/28", "172.183.143.224/28", "172.183.222.128/28", "172.202.102.112/28", "172.204.16.64/28", "172.212.159.64/28", "172.213.11.144/28", "172.213.12.112/28", "172.213.21.112/28", "172.213.21.144/28", "172.213.21.16/28", "172.215.218.96/28", "191.233.1.112/28", "191.233.1.128/28", "191.233.1.224/28", "191.233.194.32/28", "191.233.196.112/28", "191.233.199.160/28", "191.233.2.0/28", "191.234.167.128/28", "191.235.66.16/28", "191.235.98.144/28", "191.235.99.80/28", "191.237.249.64/28", "191.239.245.16/28", "20.0.53.96/28", "20.102.212.144/28", "20.117.22.224/28", "20.125.112.224/28", "20.125.144.144/28", "20.161.75.208/28", "20.168.7.192/28", "20.168.7.240/28", "20.169.72.112/28", "20.169.72.96/28", "20.169.73.176/28", "20.169.73.32/28", "20.169.73.64/28", "20.169.78.112/28", "20.169.78.128/28", "20.169.78.144/28", "20.169.78.160/28", "20.169.78.176/28", "20.169.78.192/28", "20.169.78.208/28", "20.169.78.48/28", "20.169.78.64/28", "20.169.78.80/28", "20.169.78.96/28", "20.169.86.224/28", "20.169.86.240/28", "20.169.87.112/28", "20.172.29.32/28", "20.193.233.240/28", "20.193.50.32/28", "20.194.0.208/28", "20.194.1.0/28", "20.194.157.176/28", "20.198.67.96/28", "20.203.245.32/28", "20.204.24.240/28", "20.210.154.128/28", "20.210.174.208/28", "20.210.211.192/28", "20.215.187.208/28", "20.215.188.192/28", "20.215.214.16/28", "20.215.219.128/28", "20.215.219.160/28", "20.215.219.208/28", "20.215.220.112/28", "20.215.220.128/28", "20.215.220.144/28", "20.215.220.160/28", "20.215.220.176/28", "20.215.220.192/28", "20.215.220.208/28", "20.215.220.64/28", "20.215.220.80/28", "20.215.220.96/28", "20.227.140.32/28", "20.228.106.176/28", "20.235.75.208/28", "20.235.87.224/28", "20.249.63.208/28", "20.27.94.128/28", "20.45.178.144/28", "20.55.229.144/28", "20.63.221.64/28", "20.90.7.144/28", "20.97.189.96/28", "23.102.140.144/28", "23.102.141.32/28", "23.97.109.224/28", "23.98.142.176/28", "23.98.179.16/28", "23.98.186.176/28", "23.98.186.192/28", "23.98.186.64/28", "23.98.186.96/28", "4.151.119.48/28", "4.151.241.240/28", "4.151.71.176/28", "4.189.118.208/28", "4.189.119.48/28", "4.196.118.112/28", "4.196.198.80/28", "4.197.115.112/28", "4.197.19.176/28", "4.197.22.112/28", "4.197.64.0/28", "4.197.64.16/28", "4.197.64.48/28", "4.197.64.64/28", "4.205.128.176/28", "40.116.73.208/28", "40.122.235.112/28", "40.67.183.160/28", "40.67.183.176/28", "40.75.14.224/28", "40.81.134.128/28", "40.81.134.144/28", "40.81.234.144/28", "40.84.181.32/28", "40.84.221.208/28", "40.84.221.224/28", "51.107.70.192/28", "51.8.155.112/28", "51.8.155.48/28", "51.8.155.64/28", "51.8.155.80/28", "52.148.129.32/28", "52.154.22.48/28", "52.156.77.144/28", "52.159.227.32/28", "52.159.249.96/28", "52.165.212.16/28", "52.165.212.32/28", "52.165.212.48/28", "52.172.129.160/28", "52.172.251.112/28", "52.173.123.0/28", "52.173.219.112/28", "52.173.219.96/28", "52.173.221.16/28", "52.173.221.176/28", "52.173.221.208/28", "52.173.234.16/28", "52.173.234.80/28", "52.173.235.80/28", "52.176.139.176/28", "52.187.246.128/28", "52.190.137.144/28", "52.190.137.16/28", "52.190.139.48/28", "52.190.142.64/28", "52.190.190.16/28", "52.225.75.208/28", "52.230.163.32/28", "52.230.164.176/28", "52.231.30.48/28", "52.231.34.176/28", "52.231.39.144/28", "52.231.39.192/28", "52.231.49.48/28", "52.231.50.64/28", "52.236.94.144/28", "52.242.132.224/28", "52.242.132.240/28", "52.242.245.208/28", "52.252.113.240/28", "52.255.109.112/28", "52.255.109.128/28", "52.255.109.144/28", "52.255.109.80/28", "52.255.109.96/28", "52.255.111.0/28", "52.255.111.112/28", "52.255.111.16/28", "52.255.111.32/28", "52.255.111.48/28", "52.255.111.80/28", "57.151.131.224/28", "57.154.174.112/28", "57.154.175.0/28", "57.154.187.32/28", "68.154.28.96/28", "68.218.30.112/28", "68.220.57.64/28", "68.221.67.160/28", "68.221.67.192/28", "68.221.67.224/28", "68.221.67.240/28", "68.221.75.16/28", "74.226.253.160/28", "74.249.86.176/28", "74.7.35.112/28", "74.7.35.48/28", "74.7.36.64/28", "74.7.36.80/28", "74.7.36.96/28"
    ],
    "OAI-SearchBot": [
        "104.210.140.128/28", "135.234.64.0/24", "172.182.193.224/28", "172.182.193.80/28", "172.182.194.144/28", "172.182.194.32/28", "172.182.195.48/28", "172.182.209.208/28", "172.182.211.192/28", "172.182.213.192/28", "172.182.224.0/28", "172.203.190.128/28", "20.14.99.96/28", "20.168.18.32/28", "20.169.6.224/28", "20.169.7.48/28", "20.169.77.0/25", "20.171.123.64/28", "20.171.53.224/28", "20.25.151.224/28", "20.42.10.176/28", "4.227.36.0/25", "40.67.175.0/25", "40.90.214.16/28", "51.8.102.0/24", "74.7.175.128/25", "74.7.228.0/25", "74.7.228.128/25", "74.7.229.0/25", "74.7.229.128/25", "74.7.230.0/25", "74.7.241.128/25", "74.7.242.128/25", "74.7.243.0/25", "74.7.244.0/25"
    ],
    "GPTBot": [
        "132.196.86.0/24", "172.182.202.0/25", "172.182.204.0/24", "172.182.207.0/25", "172.182.214.0/24", "172.182.215.0/24", "20.125.66.80/28", "20.171.206.0/24", "20.171.207.0/24", "4.227.36.0/25", "52.230.152.0/24", "74.7.175.128/25", "74.7.227.0/25", "74.7.227.128/25", "74.7.228.0/25", "74.7.230.0/25", "74.7.241.0/25", "74.7.241.128/25", "74.7.242.0/25", "74.7.243.128/25", "74.7.244.0/25"
    ],
    "Googlebot": [
        "192.178.4.0/27", "192.178.4.128/27", "192.178.4.160/27", "192.178.4.192/27", "192.178.4.32/27", "192.178.4.64/27", "192.178.4.96/27", "192.178.5.0/27", "192.178.6.0/27", "192.178.6.128/27", "192.178.6.160/27", "192.178.6.192/27", "192.178.6.224/27", "192.178.6.32/27", "192.178.6.64/27", "192.178.6.96/27", "192.178.7.0/27", "192.178.7.128/27", "192.178.7.160/27", "192.178.7.192/27", "192.178.7.224/27", "192.178.7.32/27", "192.178.7.64/27", "192.178.7.96/27", "34.100.182.96/28", "34.101.50.144/28", "34.118.254.0/28", "34.118.66.0/28", "34.126.178.96/28", "34.146.150.144/28", "34.147.110.144/28", "34.151.74.144/28", "34.152.50.64/28", "34.154.114.144/28", "34.155.98.32/28", "34.165.18.176/28", "34.175.160.64/28", "34.176.130.16/28", "34.22.85.0/27", "34.64.82.64/28", "34.65.242.112/28", "34.80.50.80/28", "34.88.194.0/28", "34.89.10.80/28", "34.89.198.80/28", "34.96.162.48/28", "35.247.243.240/28", "66.249.64.0/27", "66.249.64.128/27", "66.249.64.160/27", "66.249.64.192/27", "66.249.64.224/27", "66.249.64.32/27", "66.249.64.64/27", "66.249.64.96/27", "66.249.65.0/27", "66.249.65.128/27", "66.249.65.160/27", "66.249.65.192/27", "66.249.65.224/27", "66.249.65.32/27", "66.249.65.64/27", "66.249.65.96/27", "66.249.66.0/27", "66.249.66.128/27", "66.249.66.160/27", "66.249.66.192/27", "66.249.66.224/27", "66.249.66.32/27", "66.249.66.64/27", "66.249.66.96/27", "66.249.67.0/27", "66.249.67.32/27", "66.249.67.64/27", "66.249.68.0/27", "66.249.68.128/27", "66.249.68.160/27", "66.249.68.192/27", "66.249.68.32/27", "66.249.68.64/27", "66.249.68.96/27", "66.249.69.0/27", "66.249.69.128/27", "66.249.69.160/27", "66.249.69.192/27", "66.249.69.224/27", "66.249.69.32/27", "66.249.69.64/27", "66.249.69.96/27", "66.249.70.0/27", "66.249.70.128/27", "66.249.70.160/27", "66.249.70.192/27", "66.249.70.224/27", "66.249.70.32/27", "66.249.70.64/27", "66.249.70.96/27", "66.249.71.0/27", "66.249.71.128/27", "66.249.71.160/27", "66.249.71.192/27", "66.249.71.224/27", "66.249.71.32/27", "66.249.71.64/27", "66.249.71.96/27", "66.249.72.0/27", "66.249.72.128/27", "66.249.72.160/27", "66.249.72.192/27", "66.249.72.224/27", "66.249.72.32/27", "66.249.72.64/27", "66.249.73.0/27", "66.249.73.128/27", "66.249.73.160/27", "66.249.73.192/27", "66.249.73.224/27", "66.249.73.32/27", "66.249.73.64/27", "66.249.73.96/27", "66.249.74.0/27", "66.249.74.128/27", "66.249.74.160/27", "66.249.74.192/27", "66.249.74.224/27", "66.249.74.32/27", "66.249.74.64/27", "66.249.74.96/27", "66.249.75.0/27", "66.249.75.128/27", "66.249.75.160/27", "66.249.75.192/27", "66.249.75.224/27", "66.249.75.32/27", "66.249.75.64/27", "66.249.75.96/27", "66.249.76.0/27", "66.249.76.128/27", "66.249.76.160/27", "66.249.76.192/27", "66.249.76.224/27", "66.249.76.32/27", "66.249.76.64/27", "66.249.76.96/27", "66.249.77.0/27", "66.249.77.128/27", "66.249.77.160/27", "66.249.77.192/27", "66.249.77.224/27", "66.249.77.32/27", "66.249.77.64/27", "66.249.77.96/27", "66.249.78.0/27", "66.249.78.128/27", "66.249.78.160/27", "66.249.78.32/27", "66.249.78.64/27", "66.249.78.96/27", "66.249.79.0/27", "66.249.79.128/27", "66.249.79.160/27", "66.249.79.192/27", "66.249.79.224/27", "66.249.79.32/27", "66.249.79.64/27"
    ],
    "Bingbot": [
        "157.55.39.0/24", "207.46.13.0/24", "40.77.167.0/24", "13.66.139.0/24", "13.66.144.0/24", "52.167.144.0/24", "13.67.10.16/28", "13.69.66.240/28", "13.71.172.224/28", "139.217.52.0/28", "191.233.204.224/28", "20.36.108.32/28", "20.43.120.16/28", "40.79.131.208/28", "40.79.186.176/28", "52.231.148.0/28", "20.79.107.240/28", "51.105.67.0/28", "20.125.163.80/28", "40.77.188.0/22", "65.55.210.0/24", "199.30.24.0/23", "40.77.202.0/24", "40.77.139.0/25", "20.74.197.0/28", "20.15.133.160/27", "40.77.177.0/24", "40.77.178.0/23"
    ],
    "ClaudeBot": [
        "160.79.104.0/21"
    ],
    "PerplexityBot": [
        "107.20.236.150/32", "3.224.62.45/32", "18.210.92.235/32", "3.222.232.239/32", "3.211.124.183/32", "3.231.139.107/32", "18.97.1.228/30", "18.97.9.96/29"
    ],
    "Perplexity-User": [
        "44.208.221.197/32", "34.193.163.52/32", "18.97.21.0/30", "18.97.43.80/29"
    ],
    "ccbot": [
        "18.97.9.168/29", "18.97.14.80/29", "18.97.14.88/30", "98.85.178.216/32"
    ]
}

def identify_bot(ip_str):
    try:
        ip_obj = ipaddress.ip_address(ip_str)
        for bot_name, ranges in BOT_RANGES.items():
            for cidr in ranges:
                if ip_obj in ipaddress.ip_network(cidr):
                    return bot_name
    except ValueError:
        return "Invalid IP"
    return "Human/Unknown"

def process_csv(input_file, output_file):
    with open(input_file, mode='r', encoding='utf-8') as infile:
        reader = csv.DictReader(infile)
        fieldnames = reader.fieldnames + ['Bot_Identity']

        with open(output_file, mode='w', encoding='utf-8', newline='') as outfile:
            writer = csv.DictWriter(outfile, fieldnames=fieldnames)
            writer.writeheader()

            for row in reader:
                # Assuming your column is named 'IP_Address'
                ip = row.get('IP_Address', '').strip()
                row['Bot_Identity'] = identify_bot(ip)
                writer.writerow(row)

    print(f"✅ Analysis complete. File saved as: {output_file}")

# Run it
process_csv('/content/your-scraped-data.csv', 'flagged_ai_data.csv')