CrawlForge
HomePlaygroundUse CasesIntegrationsPricingDocumentationBlog
How to Use CrawlForge with Vercel AI SDK
Tutorials
Back to Blog
Tutorials

How to Use CrawlForge with Vercel AI SDK

C
CrawlForge Team
Engineering Team
April 7, 2026
8 min read
Updated April 14, 2026

On this page

Quick Answer

Register CrawlForge's 26 scraping tools with the Vercel AI SDK's tool() API so any LLM you call through generateText or streamText can fetch, extract, and research the web on demand. Setup takes under 10 minutes and works with Next.js, SvelteKit, Nuxt, or plain Node.

The Vercel AI SDK gives you a unified interface for calling LLMs from any framework -- Next.js, SvelteKit, Nuxt, or plain Node. CrawlForge gives your LLM access to live web data through 26 specialized scraping tools. Together, they let you build AI applications that can search, fetch, extract, and analyze web content in real time.

This tutorial shows you how to register CrawlForge tools with the Vercel AI SDK's tool() API, so your AI can scrape the web as naturally as it generates text.

Table of Contents

  • Prerequisites
  • How It Works: Tools in the Vercel AI SDK
  • Step 1: Create the CrawlForge Tool Wrapper
  • Step 2: Register Tools with generateText
  • Step 3: Build a Streaming Chat with Web Access
  • Advanced: Multi-Tool Research Agent
  • Credit Cost Breakdown
  • Best Practices
  • Next Steps

Prerequisites

Bash
npm install ai @ai-sdk/anthropic zod dotenv
Bash
# .env.local
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.

How It Works: Tools in the Vercel AI SDK

The Vercel AI SDK lets you define tools that the LLM can invoke during a conversation. Each tool has a name, description, parameter schema (using Zod), and an execute function. The LLM reads the tool descriptions, decides when to call them, and incorporates the results into its response.

CrawlForge's REST API maps perfectly to this pattern: each of the 26 tools becomes a callable function with typed parameters.

Step 1: Create the CrawlForge Tool Wrapper

First, build a reusable helper that calls any CrawlForge endpoint:

Typescript
// lib/crawlforge.ts
const CRAWLFORGE_BASE = 'https://crawlforge.dev/api/v1/tools';

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

  if (!response.ok) {
    throw new Error(`CrawlForge ${toolName} failed: ${response.status}`);
  }

  return response.json() as Promise<T>;
}

Step 2: Register Tools with generateText

Now register CrawlForge tools using the Vercel AI SDK's tool() function:

Typescript
// app/api/chat/route.ts
import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import { callCrawlForge } from '@/lib/crawlforge';

const result = await generateText({
  model: anthropic('claude-sonnet-4-20250514'),
  tools: {
    // Fetch and extract clean content from any URL (2 credits)
    extractContent: tool({
      description: 'Extract the main content from a web page as clean text. Use this when you need to read an article, documentation page, or any web content.',
      parameters: z.object({
        url: z.string().url().describe('The URL to extract content from'),
      }),
      execute: async ({ url }) => {
        return callCrawlForge('extract_content', { url });
      },
    }),

    // Search the web (5 credits)
    searchWeb: tool({
      description: 'Search the web using Google. Returns titles, URLs, and snippets for the top results.',
      parameters: z.object({
        query: z.string().describe('The search query'),
        limit: z.number().optional().default(5).describe('Number of results'),
      }),
      execute: async ({ query, limit }) => {
        return callCrawlForge('search_web', { query, limit });
      },
    }),

    // Extract structured data with CSS selectors (2 credits)
    scrapeStructured: tool({
      description: 'Extract specific data from a web page using CSS selectors. Use when you need structured data like prices, names, or lists.',
      parameters: z.object({
        url: z.string().url().describe('The URL to scrape'),
        selectors: z.record(z.string()).describe('CSS selectors mapping field names to selectors'),
      }),
      execute: async ({ url, selectors }) => {
        return callCrawlForge('scrape_structured', { url, selectors });
      },
    }),
  },
  prompt: 'Find the current pricing for Vercel Pro plan and compare it to Netlify Pro.',
});

console.log(result.text);

When the LLM encounters a question that requires web data, it automatically invokes the right CrawlForge tool, receives the results, and weaves them into its response. No manual orchestration needed.

Step 3: Build a Streaming Chat with Web Access

For a real-time chat experience, use streamText instead of generateText:

Typescript
// app/api/chat/route.ts
import { streamText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import { callCrawlForge } from '@/lib/crawlforge';

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: anthropic('claude-sonnet-4-20250514'),
    system: `You are a research assistant with access to live web data.
When users ask about current information, use your tools to fetch it.
Always cite the URLs you retrieved data from.`,
    messages,
    tools: {
      extractContent: tool({
        description: 'Extract main content from a URL as clean text',
        parameters: z.object({
          url: z.string().url(),
        }),
        execute: async ({ url }) =>
          callCrawlForge('extract_content', { url }),
      }),
      searchWeb: tool({
        description: 'Search the web and return top results',
        parameters: z.object({
          query: z.string(),
          limit: z.number().optional().default(5),
        }),
        execute: async ({ query, limit }) =>
          callCrawlForge('search_web', { query, limit }),
      }),
    },
    maxSteps: 5, // Allow up to 5 tool calls per response
  });

  return result.toDataStreamResponse();
}

The maxSteps: 5 parameter lets the LLM chain multiple tool calls -- for example, searching the web first, then extracting content from the top result.

Frontend Component

Typescript
// app/page.tsx
'use client';
import { useChat } from 'ai/react';

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();

  return (
    <div className="max-w-2xl mx-auto p-4">
      {messages.map((m) => (
        <div key={m.id} className="mb-4">
          <strong>{m.role === 'user' ? 'You' : 'AI'}:</strong>
          <p>{m.content}</p>
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Ask anything about the web..."
          className="w-full p-2 border rounded"
          disabled={isLoading}
        />
      </form>
    </div>
  );
}

Advanced: Multi-Tool Research Agent

Combine multiple CrawlForge tools for deeper research workflows:

Typescript
import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import { callCrawlForge } from '@/lib/crawlforge';

const research = await generateText({
  model: anthropic('claude-sonnet-4-20250514'),
  tools: {
    searchWeb: tool({
      description: 'Search Google for information',
      parameters: z.object({ query: z.string(), limit: z.number().default(5) }),
      execute: async ({ query, limit }) =>
        callCrawlForge('search_web', { query, limit }),
    }),
    extractContent: tool({
      description: 'Read the full content of a web page',
      parameters: z.object({ url: z.string().url() }),
      execute: async ({ url }) =>
        callCrawlForge('extract_content', { url }),
    }),
    analyzeContent: tool({
      description: 'Analyze text for topics, sentiment, and key entities',
      parameters: z.object({ text: z.string() }),
      execute: async ({ text }) =>
        callCrawlForge('analyze_content', { text }),
    }),
  },
  maxSteps: 10,
  prompt: `Research the current state of MCP server adoption in 2026.
    Search for recent articles, read the top 3, and analyze the key trends.
    Provide a summary with citations.`,
});

console.log(research.text);
// Returns a cited research summary using live web data

This agent will:

  1. Search Google for relevant articles (5 credits)
  2. Extract content from the top results (2 credits each)
  3. Analyze the content for themes (3 credits each)

Total cost for a 3-source research run: ~20 credits.

Credit Cost Breakdown

ToolCreditsBest For
fetch_url1Raw HTML retrieval
extract_text1Clean text extraction
extract_links1Link discovery
extract_metadata1Page metadata (title, OG tags)
extract_content2Readable content extraction
scrape_structured2CSS selector-based data extraction
summarize_content2Text summarization
analyze_content3Topic and sentiment analysis
search_web5Google search results
deep_research10Multi-source research with citations

See the full pricing breakdown for all 26 tools.

Best Practices

Minimize credit usage. Use extract_content (2 credits) instead of deep_research (10 credits) when you only need one page. The tool descriptions guide the LLM toward the cheapest option that satisfies the query.

Set maxSteps carefully. A higher maxSteps value allows more tool calls per response but consumes more credits. Start with 3-5 and increase only if the LLM consistently needs more.

Cache frequently accessed pages. If your app repeatedly fetches the same URL, cache the CrawlForge response in Redis or a database rather than re-fetching each time.

Use Zod descriptions. The .describe() strings on your Zod parameters help the LLM understand what values to pass. Be specific: "The full URL including https://" is better than "URL".

Next Steps

You now have a Vercel AI SDK application with live web access. Expand from here:

  • Add the remaining 26 CrawlForge tools as needed
  • Implement stealth mode for sites with anti-bot protection
  • Build a deep research agent for automated market analysis
  • Check the CrawlForge Quick Start for MCP client setup

Build AI apps that see the 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

vercel-ai-sdknextjsintegrationweb-scrapingai-engineeringtutorialtypescript

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

Frequently Asked Questions

How do I use CrawlForge with the Vercel AI SDK?+

Register CrawlForge's 26 scraping tools with the Vercel AI SDK's tool() API so any LLM you call through generateText or streamText can fetch, extract, and research the web on demand. Setup takes under 10 minutes and works with Next.js, SvelteKit, Nuxt, or plain Node.

What is a tool in the Vercel AI SDK?+

The Vercel AI SDK lets you define tools that the LLM can invoke during a conversation. Each tool has a name, description, parameter schema using Zod, and an execute function. The LLM reads the tool descriptions, decides when to call them, and incorporates the results into its response.

How do I minimize CrawlForge credit usage in an AI SDK app?+

Use extract_content (2 credits) instead of deep_research (10 credits) when you only need one page. Set maxSteps carefully -- start with 3-5 and increase only if needed. Cache frequently accessed pages in Redis or a database rather than re-fetching each time.

Why do Zod parameter descriptions matter for AI SDK tools?+

The .describe() strings on your Zod parameters help the LLM understand what values to pass. Be specific: "The full URL including https://" is better than "URL". Clear descriptions guide the LLM toward the cheapest tool that satisfies the query.

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 Anthropic Claude API
Tutorials

How to Use CrawlForge with Anthropic Claude API

Connect CrawlForge web scraping tools to the Claude API via tool_use. Build AI applications with live web data using TypeScript and Claude Sonnet.

C
CrawlForge Team
|
Apr 15
|
9m

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.