CrawlForge
HomePlaygroundUse CasesIntegrationsPricingDocumentationBlog
How to Use CrawlForge with Anthropic Claude API
Tutorials
Back to Blog
Tutorials

How to Use CrawlForge with Anthropic Claude API

C
CrawlForge Team
Engineering Team
April 15, 2026
9 min read

On this page

Anthropic's Claude API supports native tool use -- you define tools with JSON schemas, and Claude decides when to invoke them during a conversation. CrawlForge's 26 web scraping tools are a natural fit: they give Claude the ability to search the web, extract content, scrape structured data, and conduct deep research, all through the standard tool_use API.

This guide walks you through defining CrawlForge tools for the Claude API, handling tool use responses, and building a production-grade research assistant.

Table of Contents

  • Prerequisites
  • How Claude Tool Use Works with CrawlForge
  • Step 1: Define CrawlForge Tool Schemas
  • Step 2: Handle the Tool Use Loop
  • Step 3: Build a Research Assistant
  • Advanced: Streaming with Tool Use
  • Credit Cost Breakdown
  • Best Practices
  • Frequently Asked Questions
  • Next Steps

Prerequisites

Bash
npm install @anthropic-ai/sdk dotenv
Bash
# .env
ANTHROPIC_API_KEY=sk-ant-xxxxx
CRAWLFORGE_API_KEY=cf_live_xxxxx

Get your CrawlForge API key at crawlforge.dev/signup -- 1,000 free credits included. For Claude API access, visit console.anthropic.com and follow the API getting started guide.

How Claude Tool Use Works with CrawlForge

Claude's tool use follows a request-response loop:

  1. You send a message with tool definitions and a user prompt
  2. Claude responds with either text or a tool_use content block
  3. You execute the tool (call CrawlForge API) and return the result
  4. Claude incorporates the result and continues its response
You -> Claude: "What's on the Hacker News front page?" Claude -> You: tool_use { name: "extract_content", input: { url: "https://news.ycombinator.com" } } You -> CrawlForge: POST /api/v1/tools/extract_content { url: "..." } CrawlForge -> You: { content: "..." } You -> Claude: tool_result { content: "..." } Claude -> You: "Here are the top stories on Hacker News right now: ..."

Step 1: Define CrawlForge Tool Schemas

Define the tools Claude can use. Each tool needs a name, description, and input_schema (JSON Schema format):

Typescript
// lib/tool-definitions.ts
import Anthropic from '@anthropic-ai/sdk';

export const crawlforgeTools: Anthropic.Tool[] = [
  {
    name: 'search_web',
    description: 'Search Google and return top results. Use when you need to find web pages about a topic. Returns titles, URLs, and snippets. Costs 5 credits.',
    input_schema: {
      type: 'object' as const,
      properties: {
        query: {
          type: 'string',
          description: 'The search query',
        },
        limit: {
          type: 'number',
          description: 'Maximum number of results (default: 5)',
        },
      },
      required: ['query'],
    },
  },
  {
    name: 'extract_content',
    description: 'Extract the main readable content from a web page. Returns clean text without navigation, ads, or boilerplate. Use when you need to read a specific URL. Costs 2 credits.',
    input_schema: {
      type: 'object' as const,
      properties: {
        url: {
          type: 'string',
          description: 'The full URL to extract content from',
        },
      },
      required: ['url'],
    },
  },
  {
    name: 'scrape_structured',
    description: 'Extract specific data from a page using CSS selectors. Use when you need structured data like prices, names, or lists. Costs 2 credits.',
    input_schema: {
      type: 'object' as const,
      properties: {
        url: {
          type: 'string',
          description: 'The URL to scrape',
        },
        selectors: {
          type: 'object',
          description: 'Map of field names to CSS selectors',
          additionalProperties: { type: 'string' },
        },
      },
      required: ['url', 'selectors'],
    },
  },
  {
    name: 'fetch_url',
    description: 'Fetch raw HTML from a URL. Cheapest option at 1 credit. Use for APIs or when you need the raw HTML.',
    input_schema: {
      type: 'object' as const,
      properties: {
        url: {
          type: 'string',
          description: 'The URL to fetch',
        },
      },
      required: ['url'],
    },
  },
  {
    name: 'extract_metadata',
    description: 'Get page metadata including title, description, Open Graph tags, and other meta information. Costs 1 credit.',
    input_schema: {
      type: 'object' as const,
      properties: {
        url: {
          type: 'string',
          description: 'The URL to extract metadata from',
        },
      },
      required: ['url'],
    },
  },
];

Step 2: Handle the Tool Use Loop

The core pattern: send messages to Claude, check if it wants to use a tool, execute the tool via CrawlForge, and return the result.

Typescript
// lib/agent.ts
import Anthropic from '@anthropic-ai/sdk';
import { crawlforgeTools } from './tool-definitions';

const client = new Anthropic();
const CRAWLFORGE_BASE = 'https://crawlforge.dev/api/v1/tools';

// Execute a CrawlForge tool
async function executeTool(
  name: string,
  input: Record<string, unknown>
): Promise<string> {
  const response = await fetch(`${CRAWLFORGE_BASE}/${name}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CRAWLFORGE_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(input),
  });

  if (!response.ok) {
    return JSON.stringify({ error: `HTTP ${response.status}: ${response.statusText}` });
  }

  const data = await response.json();
  return JSON.stringify(data);
}

// Run Claude with CrawlForge tools
export async function askClaude(prompt: string): Promise<string> {
  const messages: Anthropic.MessageParam[] = [
    { role: 'user', content: prompt },
  ];

  // Tool use loop: keep going until Claude gives a final text response
  while (true) {
    const response = await client.messages.create({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 4096,
      tools: crawlforgeTools,
      messages,
    });

    // Check if Claude wants to use a tool
    if (response.stop_reason === 'tool_use') {
      // Add Claude's response to message history
      messages.push({ role: 'assistant', content: response.content });

      // Execute each tool call and collect results
      const toolResults: Anthropic.ToolResultBlockParam[] = [];

      for (const block of response.content) {
        if (block.type === 'tool_use') {
          const result = await executeTool(
            block.name,
            block.input as Record<string, unknown>
          );
          toolResults.push({
            type: 'tool_result',
            tool_use_id: block.id,
            content: result,
          });
        }
      }

      // Return tool results to Claude
      messages.push({ role: 'user', content: toolResults });
    } else {
      // Claude gave a final text response
      const textBlock = response.content.find(b => b.type === 'text');
      return textBlock ? textBlock.text : '';
    }
  }
}

// Usage
const answer = await askClaude(
  'What are the top 3 trending repositories on GitHub right now?'
);
console.log(answer);

This loop handles multi-step tool use automatically. Claude might search, then extract content from a result, then search again -- the loop continues until it produces a final text response.

Step 3: Build a Research Assistant

Wrap the agent in a more structured application:

Typescript
// research-assistant.ts
import { askClaude } from './lib/agent';

async function researchTopic(topic: string, depth: 'quick' | 'thorough' = 'quick') {
  const systemPrompt = depth === 'thorough'
    ? `Research this topic thoroughly. Search for at least 3 different sources,
       read each one, and provide a comprehensive summary with citations.
       Topic: ${topic}`
    : `Quickly answer this question using web search if needed.
       Be concise and cite your source. Topic: ${topic}`;

  console.log(`Researching: ${topic} (mode: ${depth})`);
  const result = await askClaude(systemPrompt);
  console.log(result);
  return result;
}

// Quick research: ~7 credits (search + 1 extract)
await researchTopic('What is the current version of Next.js?', 'quick');

// Thorough research: ~11-15 credits (search + 3 extracts)
await researchTopic(
  'Compare the performance of Bun vs Node.js for HTTP servers in 2026',
  'thorough'
);

Advanced: Streaming with Tool Use

For a better user experience, use streaming to show Claude's thinking in real time:

Typescript
// lib/streaming-agent.ts
import Anthropic from '@anthropic-ai/sdk';
import { crawlforgeTools } from './tool-definitions';

const client = new Anthropic();
const CRAWLFORGE_BASE = 'https://crawlforge.dev/api/v1/tools';

async function executeTool(
  name: string,
  input: Record<string, unknown>
): Promise<string> {
  const response = await fetch(`${CRAWLFORGE_BASE}/${name}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CRAWLFORGE_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(input),
  });
  return JSON.stringify(await response.json());
}

export async function streamWithTools(prompt: string) {
  const messages: Anthropic.MessageParam[] = [
    { role: 'user', content: prompt },
  ];

  while (true) {
    const stream = client.messages.stream({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 4096,
      tools: crawlforgeTools,
      messages,
    });

    // Collect streamed text
    let hasToolUse = false;

    stream.on('text', (text) => {
      process.stdout.write(text); // Stream to terminal in real time
    });

    const response = await stream.finalMessage();

    if (response.stop_reason === 'tool_use') {
      hasToolUse = true;
      messages.push({ role: 'assistant', content: response.content });

      const toolResults: Anthropic.ToolResultBlockParam[] = [];
      for (const block of response.content) {
        if (block.type === 'tool_use') {
          console.log(`\n[Calling ${block.name}...]\n`);
          const result = await executeTool(
            block.name,
            block.input as Record<string, unknown>
          );
          toolResults.push({
            type: 'tool_result',
            tool_use_id: block.id,
            content: result,
          });
        }
      }

      messages.push({ role: 'user', content: toolResults });
    }

    if (!hasToolUse) break;
  }
}

// Usage: streams text to stdout as Claude generates it
await streamWithTools('What is CrawlForge MCP and how does it compare to Firecrawl?');

Credit Cost Breakdown

WorkflowTools UsedCredits
Quick answer (1 page)extract_content2
Search + read top resultsearch_web + extract_content7
Thorough research (3 sources)search_web + 3x extract_content11
Structured data extractionscrape_structured2
Page metadata checkextract_metadata1
Raw HTML fetchfetch_url1
Deep multi-source reportdeep_research10

The Free tier (1,000 one-time credits) supports approximately 140 single-page extractions or 90 search-and-read workflows to start. The Hobby plan ($19/month, 5,000 credits) is ideal for development and light production use.

Best Practices

Write descriptive tool descriptions. Claude uses the description field to decide which tool to call. Include what the tool does, when to use it, and its credit cost. "Extract the main readable content from a web page" is better than "Get content".

Include credit costs in descriptions. When Claude knows that fetch_url costs 1 credit and deep_research costs 10, it naturally chooses the cheaper option for simple tasks.

Handle errors gracefully. Return error messages as tool results rather than throwing exceptions. Claude can adapt its strategy when a tool fails -- for example, trying a different URL or rephrasing a search.

Set max_tokens appropriately. Web content can be long. Set max_tokens to at least 4096 to give Claude room to incorporate tool results into comprehensive responses.

Use system prompts to guide tool use. Tell Claude when to search vs. when to directly access a known URL. This prevents unnecessary search_web calls (5 credits) when a direct extract_content (2 credits) would suffice.

Frequently Asked Questions

Can I use CrawlForge with Claude 3.5 Haiku for lower costs?

Yes. All Claude models that support tool use work with CrawlForge tools. Haiku is cheaper per token but may need more explicit instructions to select the right tool. Claude Sonnet provides the best balance of cost and tool-use accuracy.

How do I handle rate limits?

CrawlForge's API includes rate limiting headers (X-RateLimit-Remaining). If you hit a 429 response, add a retry with exponential backoff. For high-volume use, the Professional plan includes higher rate limits.

Can Claude call multiple CrawlForge tools in one turn?

Yes. Claude can request multiple tool uses in a single response. The tool use loop in Step 2 handles this -- it iterates over all tool_use blocks and returns all results at once.

What happens when CrawlForge credits run out?

The API returns a 402 Payment Required error. Return this as a tool result so Claude can inform the user. You can check remaining credits via the dashboard or the credits API endpoint.

Next Steps

You now have a Claude-powered application with live web access. Explore further:

  • CrawlForge Quick Start for native MCP integration with Claude Code
  • All 26 tools explained with credit costs and usage examples
  • Building an AI Research Assistant with Claude and CrawlForge
  • CrawlForge vs Firecrawl comparison for choosing the right tool

Give Claude access to the live web. Start free with 1,000 credits -- no credit card required.

Try this yourself — no signup needed

Run any of CrawlForge's 27 scraping and extraction tools in the playground, then start free with 1,000 credits.

1,000 free credits • Refills monthly • No credit card required

Tags

anthropicclaude-apitool-useintegrationweb-scrapingtutorialtypescript

About the Author

C

CrawlForge Team

Engineering Team

Building the most comprehensive web scraping MCP server. We create tools that help developers extract, analyze, and transform web data for AI applications.

Stay updated with the latest insights

Get tutorials, product updates, and web scraping tips delivered to your inbox.

No spam. Unsubscribe anytime.

Put this into practice

Test CrawlForge's tools on any URL — free, no signup.

On this page

Related Articles

How to Use CrawlForge with LangGraph Agents
Tutorials

How to Use CrawlForge with LangGraph Agents

Build stateful web scraping agents with LangGraph and CrawlForge. TypeScript guide covering graph nodes, state management, and conditional scraping flows.

C
CrawlForge Team
|
Apr 24
|
8m
How to Use CrawlForge with Mastra AI Agents
Tutorials

How to Use CrawlForge with Mastra AI Agents

Build AI agents with web scraping capabilities using Mastra and CrawlForge. TypeScript setup guide with tool integration, workflows, and agent examples.

C
CrawlForge Team
|
Apr 21
|
7m
How to Use CrawlForge with Vercel AI SDK
Tutorials

How to Use CrawlForge with Vercel AI SDK

Build AI apps with live web data using CrawlForge and the Vercel AI SDK. Add web scraping tools to your LLM chatbot or agent in under 10 minutes.

C
CrawlForge Team
|
Apr 7
|
8m

Footer

CrawlForge

Enterprise web scraping for AI Agents. 27 specialized MCP tools designed for modern developers building intelligent systems.

Product

  • Features
  • Playground
  • Pricing
  • Use Cases
  • Integrations
  • Alternatives
  • Changelog

Resources

  • Getting Started
  • API Reference
  • Templates
  • Guides
  • Blog
  • Glossary
  • FAQ
  • Sitemap

Developers

  • MCP Protocol
  • Claude Desktop
  • Cursor IDE
  • LangChain
  • LlamaIndex

Company

  • About
  • Contact
  • Privacy
  • Terms
  • Acceptable Use
  • Cookies

Stay updated

Get the latest updates on new tools and features.

Built with Next.js and MCP protocol

© 2025-2026 CrawlForge. All rights reserved.