Table of contents

How do I get started with the Claude API for web scraping?

Getting started with the Claude API for web scraping involves setting up your API credentials, understanding the API endpoints, and integrating Claude's AI capabilities into your scraping workflow. Claude excels at parsing unstructured HTML data, extracting specific information, and transforming web content into structured formats without complex CSS selectors or XPath expressions.

Understanding Claude API for Web Scraping

Claude API is a powerful large language model (LLM) that can understand and extract data from HTML content intelligently. Unlike traditional web scraping tools that require precise selectors, Claude can interpret web pages contextually and extract relevant information based on natural language instructions.

Key Benefits

  • Intelligent parsing: Extract data without writing complex selectors
  • Flexibility: Handles varying HTML structures and layouts
  • Natural language instructions: Describe what you want to extract in plain English
  • Structured output: Get JSON responses directly from unstructured HTML
  • Error handling: Claude can adapt to minor changes in page structure

Setting Up Your Claude API Account

Step 1: Create an Anthropic Account

  1. Visit Anthropic's Console
  2. Sign up for an account or log in
  3. Navigate to the API Keys section
  4. Generate a new API key
  5. Store your API key securely (never commit it to version control)

Step 2: Install Required Dependencies

For Python:

pip install anthropic requests beautifulsoup4

For Node.js:

npm install @anthropic-ai/sdk axios cheerio

Basic Authentication and Setup

Python Example

import os
from anthropic import Anthropic

# Initialize the Claude client
client = Anthropic(
    api_key=os.environ.get("ANTHROPIC_API_KEY")
)

# Verify your setup
def test_connection():
    message = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "Hello, Claude!"}
        ]
    )
    print(message.content)

test_connection()

JavaScript Example

import Anthropic from '@anthropic-ai/sdk';

// Initialize the Claude client
const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

// Verify your setup
async function testConnection() {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 1024,
    messages: [
      { role: 'user', content: 'Hello, Claude!' }
    ],
  });

  console.log(message.content);
}

testConnection();

Building Your First Web Scraping Script with Claude

Step 1: Fetch HTML Content

First, you need to retrieve the HTML content from the target website. You can use traditional HTTP libraries for this step.

Python implementation:

import requests
from anthropic import Anthropic
import json
import os

def fetch_html(url):
    """Fetch HTML content from a URL"""
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.text

# Example usage
html_content = fetch_html('https://example.com/products')

JavaScript implementation:

import axios from 'axios';

async function fetchHTML(url) {
  const response = await axios.get(url, {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
  });
  return response.data;
}

// Example usage
const htmlContent = await fetchHTML('https://example.com/products');

Step 2: Extract Data Using Claude

Now, use Claude to intelligently extract structured data from the HTML.

Python example:

def extract_data_with_claude(html_content, extraction_prompt):
    """Use Claude to extract structured data from HTML"""
    client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

    message = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=4096,
        messages=[
            {
                "role": "user",
                "content": f"""Extract the following information from this HTML and return it as JSON:

{extraction_prompt}

HTML Content:
{html_content}

Return only valid JSON, no additional text."""
            }
        ]
    )

    # Parse the JSON response
    response_text = message.content[0].text
    return json.loads(response_text)

# Example usage
extraction_prompt = """
Extract all product information including:
- product name
- price
- description
- availability status
Return as an array of products.
"""

products = extract_data_with_claude(html_content, extraction_prompt)
print(json.dumps(products, indent=2))

JavaScript example:

async function extractDataWithClaude(htmlContent, extractionPrompt) {
  const client = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY,
  });

  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 4096,
    messages: [
      {
        role: 'user',
        content: `Extract the following information from this HTML and return it as JSON:

${extractionPrompt}

HTML Content:
${htmlContent}

Return only valid JSON, no additional text.`
      }
    ],
  });

  // Parse the JSON response
  const responseText = message.content[0].text;
  return JSON.parse(responseText);
}

// Example usage
const extractionPrompt = `
Extract all product information including:
- product name
- price
- description
- availability status
Return as an array of products.
`;

const products = await extractDataWithClaude(htmlContent, extractionPrompt);
console.log(JSON.stringify(products, null, 2));

Advanced Web Scraping Techniques

Using Claude with Dynamic Content

For JavaScript-rendered pages, combine Claude with headless browsers. When handling AJAX requests using Puppeteer, you can wait for content to load before passing it to Claude.

Python with Playwright:

from playwright.sync_api import sync_playwright
from anthropic import Anthropic
import os

def scrape_dynamic_page(url, extraction_prompt):
    """Scrape JavaScript-rendered pages using Playwright + Claude"""
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        page.goto(url)

        # Wait for content to load
        page.wait_for_selector('.product-list')

        # Get the rendered HTML
        html_content = page.content()
        browser.close()

    # Extract data with Claude
    client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
    message = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=4096,
        messages=[
            {
                "role": "user",
                "content": f"{extraction_prompt}\n\nHTML:\n{html_content}"
            }
        ]
    )

    return message.content[0].text

# Example usage
result = scrape_dynamic_page(
    'https://example.com/spa-products',
    'Extract product titles and prices as JSON array'
)
print(result)

Handling Pagination

When scraping multiple pages, Claude can help extract pagination links and navigate through results.

def scrape_with_pagination(base_url):
    """Scrape multiple pages using Claude to detect pagination"""
    all_data = []
    current_url = base_url

    while current_url:
        html = fetch_html(current_url)

        # Extract data from current page
        data = extract_data_with_claude(html, "Extract all articles with title and date")
        all_data.extend(data)

        # Ask Claude to find the next page URL
        client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
        message = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=256,
            messages=[
                {
                    "role": "user",
                    "content": f"""From this HTML, extract the "next page" URL.
Return only the URL or "null" if there is no next page.

HTML: {html}"""
                }
            ]
        )

        next_url = message.content[0].text.strip()
        current_url = None if next_url == "null" else next_url

    return all_data

Best Practices for Claude API Web Scraping

1. Optimize Token Usage

HTML pages can be large. Clean unnecessary content before sending to Claude:

from bs4 import BeautifulSoup

def clean_html(html_content):
    """Remove scripts, styles, and unnecessary tags to reduce tokens"""
    soup = BeautifulSoup(html_content, 'html.parser')

    # Remove script and style elements
    for element in soup(['script', 'style', 'nav', 'footer', 'header']):
        element.decompose()

    # Get main content area if identifiable
    main_content = soup.find('main') or soup.find('article') or soup.body

    return str(main_content) if main_content else str(soup)

2. Structure Your Prompts Effectively

Be specific about the output format and data structure:

structured_prompt = """
Extract product information and return as JSON with this exact structure:
{
  "products": [
    {
      "name": "string",
      "price": "number",
      "currency": "string",
      "inStock": "boolean",
      "rating": "number or null"
    }
  ]
}

Only include products that are clearly visible on the page.
"""

3. Handle Errors Gracefully

import time
from anthropic import APIError

def extract_with_retry(html_content, prompt, max_retries=3):
    """Extract data with exponential backoff retry logic"""
    client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

    for attempt in range(max_retries):
        try:
            message = client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=4096,
                messages=[
                    {"role": "user", "content": f"{prompt}\n\nHTML:\n{html_content}"}
                ]
            )
            return json.loads(message.content[0].text)
        except APIError as e:
            if attempt == max_retries - 1:
                raise
            wait_time = 2 ** attempt
            print(f"API error, retrying in {wait_time}s...")
            time.sleep(wait_time)

4. Respect Rate Limits

Implement rate limiting to avoid API throttling:

import time
from datetime import datetime, timedelta

class RateLimiter:
    def __init__(self, requests_per_minute=50):
        self.requests_per_minute = requests_per_minute
        self.requests = []

    def wait_if_needed(self):
        now = datetime.now()
        minute_ago = now - timedelta(minutes=1)

        # Remove old requests
        self.requests = [req for req in self.requests if req > minute_ago]

        if len(self.requests) >= self.requests_per_minute:
            sleep_time = 60 - (now - self.requests[0]).seconds
            time.sleep(sleep_time)

        self.requests.append(now)

# Usage
limiter = RateLimiter(requests_per_minute=50)

for url in urls:
    limiter.wait_if_needed()
    html = fetch_html(url)
    data = extract_data_with_claude(html, prompt)

Combining Claude with Traditional Scraping Tools

For optimal results, combine Claude's AI capabilities with traditional scraping tools. Similar to how you might handle browser sessions in Puppeteer, you can use Puppeteer for navigation and Claude for data extraction:

import puppeteer from 'puppeteer';
import Anthropic from '@anthropic-ai/sdk';

async function hybridScraping(url) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto(url, { waitUntil: 'networkidle0' });

  // Get the rendered HTML
  const html = await page.content();
  await browser.close();

  // Use Claude to extract data
  const client = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY,
  });

  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 4096,
    messages: [
      {
        role: 'user',
        content: `Extract all product data as JSON array:\n\n${html}`
      }
    ],
  });

  return JSON.parse(message.content[0].text);
}

Cost Considerations

Claude API pricing is based on input and output tokens. To minimize costs:

  • Clean HTML before sending (remove scripts, styles, navigation)
  • Use specific selectors to extract only relevant sections
  • Cache results when scraping similar pages
  • Batch requests when possible
  • Choose the right model: Claude 3.5 Sonnet offers the best balance of performance and cost for web scraping

Token Estimation

def estimate_tokens(text):
    """Rough estimation: ~4 characters per token"""
    return len(text) / 4

html_content = fetch_html(url)
cleaned_html = clean_html(html_content)

print(f"Original tokens: ~{estimate_tokens(html_content)}")
print(f"Cleaned tokens: ~{estimate_tokens(cleaned_html)}")
print(f"Token reduction: {(1 - len(cleaned_html)/len(html_content)) * 100:.1f}%")

Complete Working Example

Here's a production-ready example combining all best practices:

import os
import json
import time
import requests
from bs4 import BeautifulSoup
from anthropic import Anthropic, APIError

class ClaudeScraper:
    def __init__(self, api_key=None):
        self.client = Anthropic(api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"))
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })

    def fetch_page(self, url):
        """Fetch and clean HTML content"""
        response = self.session.get(url)
        response.raise_for_status()

        soup = BeautifulSoup(response.text, 'html.parser')
        for element in soup(['script', 'style', 'nav', 'footer']):
            element.decompose()

        return str(soup)

    def extract_data(self, html, prompt, max_retries=3):
        """Extract structured data using Claude with retry logic"""
        for attempt in range(max_retries):
            try:
                message = self.client.messages.create(
                    model="claude-3-5-sonnet-20241022",
                    max_tokens=4096,
                    messages=[
                        {
                            "role": "user",
                            "content": f"{prompt}\n\nHTML:\n{html}"
                        }
                    ]
                )

                response_text = message.content[0].text
                return json.loads(response_text)

            except (APIError, json.JSONDecodeError) as e:
                if attempt == max_retries - 1:
                    raise
                time.sleep(2 ** attempt)

    def scrape(self, url, extraction_prompt):
        """Complete scraping workflow"""
        html = self.fetch_page(url)
        return self.extract_data(html, extraction_prompt)

# Usage
scraper = ClaudeScraper()

prompt = """
Extract all article information as JSON:
{
  "articles": [
    {"title": "string", "author": "string", "date": "string", "summary": "string"}
  ]
}
"""

data = scraper.scrape('https://example.com/blog', prompt)
print(json.dumps(data, indent=2))

Conclusion

Getting started with the Claude API for web scraping opens up powerful possibilities for intelligent data extraction. By combining Claude's natural language understanding with traditional web scraping techniques, you can build robust, flexible scrapers that adapt to changing page structures and extract complex information without brittle selectors.

Start with simple extraction tasks, optimize your prompts, and gradually incorporate more advanced features like pagination handling and error recovery. As you become familiar with the API, you'll discover that Claude can handle increasingly sophisticated scraping challenges with minimal code.

For production web scraping needs with built-in proxy rotation, JavaScript rendering, and API-based access, consider using specialized services like WebScraping.AI that combine AI-powered extraction with enterprise-grade infrastructure.

Try WebScraping.AI for Your Web Scraping Needs

Looking for a powerful web scraping solution? WebScraping.AI provides an LLM-powered API that combines Chromium JavaScript rendering with rotating proxies for reliable data extraction.

Key Features:

  • AI-powered extraction: Ask questions about web pages or extract structured data fields
  • JavaScript rendering: Full Chromium browser support for dynamic content
  • Rotating proxies: Datacenter and residential proxies from multiple countries
  • Easy integration: Simple REST API with SDKs for Python, Ruby, PHP, and more
  • Reliable & scalable: Built for developers who need consistent results

Getting Started:

Get page content with AI analysis:

curl "https://api.webscraping.ai/ai/question?url=https://example.com&question=What is the main topic?&api_key=YOUR_API_KEY"

Extract structured data:

curl "https://api.webscraping.ai/ai/fields?url=https://example.com&fields[title]=Page title&fields[price]=Product price&api_key=YOUR_API_KEY"

Try in request builder

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon