Skip to main content
Vercel AI SDK is a TypeScript toolkit for building AI applications with React, Next.js, Vue, Svelte, Node.js, and more. It provides a unified API for working with different AI providers and includes utilities for streaming, function calling, and building conversational interfaces.

Steps to Get Started

1

Prerequisites

  • Bright Data API Key
  • Node.js 20.18.1+
  • TypeScript (recommended)
2

Installation

Install the required packages:
npm install @brightdata/sdk ai zod
3

Create Bright Data Tools

Create a file brightdata-tools.ts with the following content:
brightdata-tools.ts
import { tool, type Tool } from 'ai'
import { z } from 'zod'
import { bdclient } from '@brightdata/sdk'

type BrightDataTools = 'scrape' | 'search' | 'amazonProduct'|'linkedinCollectProfiles'

interface BrightDataToolsConfig {
  apiKey: string
  excludeTools?: BrightDataTools[]
}

export const brightDataTools = (
  config: BrightDataToolsConfig
): Partial<Record<BrightDataTools, Tool>> => {
  const client = new bdclient({ 
    apiKey: config.apiKey,
    autoCreateZones: true
  })

  const tools: Partial<Record<BrightDataTools, Tool>> = {
    scrape: tool({
      description:
        'Scrape website content and return it in clean markdown format. Bypasses anti-bot protection and CAPTCHAs.',
      inputSchema: z.object({
        url: z
          .string()
          .url()
          .describe('The URL of the website to scrape'),
        country: z
          .string()
          .length(2)
          .optional()
          .describe('Two-letter country code for proxy location (e.g., "us", "gb", "de")'),
      }),
      execute: async ({ url, country }) => {
        try {
          const result = await client.scrape(url, {
            dataFormat: 'markdown',
            format: 'raw',
            country: country?.toLowerCase(),
          })
          return result
        } catch (error) {
          return `Error scraping ${url}: ${String(error)}`
        }
      },
    }),

    search: tool({
      description:
        'Search the web using Google, Bing, or Yandex. Returns search results with anti-bot protection bypass.',
      inputSchema: z.object({
        query: z
          .string()
          .describe('The search query'),
        searchEngine: z
          .enum(['google', 'bing', 'yandex'])
          .optional()
          .default('google')
          .describe('Search engine to use'),
        country: z
          .string()
          .length(2)
          .optional()
          .describe('Two-letter country code for localized results'),
        dataFormat: z
          .enum(['html', 'markdown'])
          .optional()
          .default('markdown')
          .describe('Format of returned search results'),
      }),
      execute: async ({ query, searchEngine, country, dataFormat }) => {
        try {
          const result = await client.search(query, {
            searchEngine,
            dataFormat,
            format: 'raw',
            country: country?.toLowerCase(),
          })
          return result
        } catch (error) {
          return `Error searching for "${query}": ${String(error)}`
        }
      },
    }),

    amazonProduct: tool({
      description:
        'Get detailed Amazon product information including price, ratings, reviews, and specifications. Requires a valid Amazon product URL.',
      inputSchema: z.object({
        url: z
          .string()
          .url()
          .describe('Amazon product URL (must contain /dp/ or /gp/product/)'),
        zipcode: z
          .string()
          .optional()
          .describe('ZIP code for location-specific pricing and availability'),
      }),
      execute: async ({ url, zipcode }) => {
        try {
          const result = await client.datasets.amazon.collectProducts(
            [{ url, zipcode }],
            { 
              format: 'json',
              async: false 
            }
          )
          return JSON.stringify(result, null, 2)
        } catch (error) {
          return `Error fetching Amazon product data: ${String(error)}`
        }
      },
    }),

    linkedinCollectProfiles: tool({
        description:
          'Fetch LinkedIn profile data for one or more LinkedIn profile URLs. Returns detailed information including work experience, education, skills, and contact information.',
        inputSchema: z.object({
          urls: z
            .array(z.string().url())
            .min(1)
            .describe('Array of LinkedIn profile URLs to collect data from (e.g., ["https://www.linkedin.com/in/example"])'),
          format: z
            .enum(['json', 'jsonl'])
            .optional()
            .default('json')
            .describe('Output format for the results'),
        }),
        execute: async ({ urls, format }) => {
          try {
            const result = await client.datasets.linkedin.collectProfiles(
              urls,
              {
                format: format || 'json',
                async: false
              }
            )
            return JSON.stringify(result, null, 2)
          } catch (error) {
            return `Error fetching LinkedIn profiles: ${String(error)}`
          }
        },
      }),
  }

  // Remove excluded tools
  for (const toolName in tools) {
    if (config.excludeTools?.includes(toolName as BrightDataTools)) {
      delete tools[toolName as BrightDataTools]
    }
  }

  return tools
}
4

Usage Examples

  • Next.js App Router
  • Node.js Script
  • Exclude Specific Tools
  • Advanced: Multiple Datasets
Create an API route that uses Bright Data tools with any AI provider:
app/api/chat/route.ts
import { openai } from '@ai-sdk/openai'
import { streamText, stepCountIs } from 'ai'
import { brightDataTools } from '@/lib/brightdata-tools'

export const maxDuration = 60

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

  const tools = brightDataTools({
    apiKey: process.env.BRIGHTDATA_API_KEY!,
  })

  const result = streamText({
    model: openai('gpt-4o'),
    messages,
    tools,
    stopWhen: stepCountIs(10),
  })

  return result.toDataStreamResponse()
}
Then use it in your component:
app/page.tsx
'use client'

import { useChat } from 'ai/react'

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

  return (
    <div className="flex flex-col h-screen">
      <div className="flex-1 overflow-y-auto p-4">
        {messages.map((m) => (
          <div key={m.id} className="mb-4">
            <strong>{m.role === 'user' ? 'You: ' : 'AI: '}</strong>
            {m.content}
          </div>
        ))}
      </div>
      <form onSubmit={handleSubmit} className="p-4 border-t">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Try: 'Scrape https://example.com' or 'Search for best laptops 2024'"
          className="w-full p-2 border rounded"
        />
      </form>
    </div>
  )
}

Example Output

Scraping Example

User Input: “Scrape https://example.com and tell me what it’s about” AI Response:
I've scraped the website. Here's what I found:

# Example Domain

This domain is for use in illustrative examples in documents. You may use this 
domain in literature without prior coordination or asking for permission.

The website appears to be a placeholder domain used for documentation and 
examples. It's maintained by IANA (Internet Assigned Numbers Authority) and 
serves as a standard example domain that can be referenced in documentation 
without needing permission.

Search Example

User Input: “Search for best mechanical keyboards 2024” AI Response:
I found several highly-rated mechanical keyboards for 2024:

1. **Keychron Q1 Pro** - A premium 75% layout keyboard with hot-swappable 
   switches, wireless connectivity, and excellent build quality. Price around $200.

2. **Wooting 60HE** - Features analog switches that allow for adjustable 
   actuation points and rapid trigger technology. Popular among gamers.

3. **GMMK Pro** - A versatile 75% gasket-mounted keyboard with extensive 
   customization options and strong community support.

All three offer different features depending on whether you prioritize gaming, 
typing, or customization.

Amazon Product Example

User Input: “Get information about Amazon product B0D2Q9397Y” AI Response:
I've retrieved the product information:

**Product:** Logitech MX Master 3S Wireless Mouse
**Price:** $99.99
**Rating:** 4.6/5 stars (8,234 reviews)
**Key Features:**
- 8K DPI sensor for precise tracking
- Quiet clicks technology
- USB-C charging
- Multi-device connectivity (up to 3 devices)
- Customizable buttons

The product has excellent reviews, with users praising its ergonomics and 
productivity features. However, some note it's on the pricier side. It's 
particularly popular among creative professionals and developers.

Available Tools

ToolDescriptionUse Cases
scrapeScrape any website and return markdownContent extraction, monitoring, and data collection
searchSearch Google, Bing, or YandexResearch, competitive analysis, trend monitoring
amazonProductGet Amazon product detailsPrice monitoring, product research, and comparison
linkedinCollectProfilesGet LinkedIn profile detailsData enrichment, people research

Additional Dataset Tools

The Bright Data SDK supports many more datasets that you can integrate:
  • LinkedIn: Profiles, companies, jobs, posts
  • Instagram: Profiles, posts, reels, comments
  • Facebook: Posts, marketplace, events, reviews
  • Twitter/X: Posts and profiles
  • TikTok: Videos, profiles, comments
  • Google Maps: Reviews and business information
  • E-commerce: Walmart, eBay, Best Buy, Etsy, Zara
Refer to the Bright Data SDK documentation for complete dataset options.

Best Practices

  1. Error Handling: Always wrap tool executions in try-catch blocks
  2. Rate Limiting: Be mindful of API rate limits when making multiple requests
  3. Data Format: Use markdown format for scraping to get clean, readable content
  4. Async Operations: For large datasets, use async: true to avoid timeouts
  5. Country Targeting: Use country codes for localized results when needed

Environment Variables

.env.local
BRIGHTDATA_API_KEY=your_api_key_here
Get your API key from the Bright Data Dashboard.
I