Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with SpyFu

Integrate SpyFu with Bolt.new via a Next.js API route that proxies all requests to the SpyFu REST API, keeping your API key in server-side environment variables. SpyFu's API provides competitor organic and paid keyword history, ad copy samples, and domain comparisons. API access requires a paid SpyFu plan. Deploy to Netlify or Bolt Cloud before testing any webhooks.

What you'll learn

  • How to authenticate with the SpyFu REST API using HTTP Basic Auth in a Next.js API route
  • How to fetch competitor organic keyword rankings and paid keyword history
  • How to build a competitive intelligence dashboard comparing domains side by side
  • How to retrieve PPC ad copy and budget estimates for competitor domains
  • How to handle SpyFu's pagination for large keyword result sets
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate13 min read25 minutesSEOApril 2026RapidDev Engineering Team
TL;DR

Integrate SpyFu with Bolt.new via a Next.js API route that proxies all requests to the SpyFu REST API, keeping your API key in server-side environment variables. SpyFu's API provides competitor organic and paid keyword history, ad copy samples, and domain comparisons. API access requires a paid SpyFu plan. Deploy to Netlify or Bolt Cloud before testing any webhooks.

Build a Competitor Intelligence Dashboard with SpyFu and Bolt.new

SpyFu's core differentiator is historical competitive intelligence. While other SEO tools show you what competitors rank for today, SpyFu shows you what they've ranked for over the past 15+ years — which keywords they've consistently owned, which PPC ads they've run for years versus tested briefly, and how their organic visibility has changed through Google algorithm updates. This historical depth makes SpyFu especially valuable for understanding long-term competitor strategies and identifying stable keyword opportunities versus volatile ones.

Integrating SpyFu with Bolt.new follows the standard server-side proxy pattern. SpyFu's API uses HTTP Basic Authentication where your API key is the username and the password is left empty. Since credentials encoded in HTTP Basic Auth headers are easily decoded from base64, they must never touch client-side code. A Next.js API route handles authentication server-side, calls SpyFu, and returns clean JSON to the browser. SpyFu's API returns well-structured JSON directly — no CSV parsing required, unlike some SEO platforms.

SpyFu's most searched use case is competitor keyword spying: enter a competitor's domain and see every keyword they rank for organically, every keyword they've bid on in Google Ads, their estimated monthly ad spend, their best-performing ad copy, and their organic ranking history. This data drives content strategy (what topics is the competitor consistently winning?), PPC strategy (which keywords have they proven to convert?), and link building strategy (which keyword rankings can be realistically targeted?). The dashboard patterns in this guide cover these core use cases with copy-paste-ready Bolt prompts.

Integration method

Bolt Chat + API Route

SpyFu's REST API uses HTTP Basic Authentication with your API key as the username. Because credentials must never appear in client-side code, all calls are proxied through a Next.js API route that injects authentication from environment variables. The API returns JSON responses, making parsing straightforward. SpyFu's unique value is historical competitor data — organic keyword history going back years and complete PPC ad campaign archives.

Prerequisites

  • A SpyFu paid account with API access (Basic, Professional, or Team plan)
  • Your SpyFu API key from the SpyFu account settings or API documentation page
  • A Bolt.new project using Next.js (required for server-side API credential handling)
  • Understanding of SEO metrics: organic rankings, keyword search volume, PPC bid data
  • A deployed Netlify or Bolt Cloud URL if you plan to share the dashboard externally

Step-by-step guide

1

Get Your SpyFu API Key and Review Pricing

Log into your SpyFu account and navigate to the API documentation page at api.spyfu.com or find the API credentials section in your account settings. SpyFu's API uses HTTP Basic Authentication — your API key acts as the username, and the password field is left empty. Copy the API key and store it securely. Before building, note that SpyFu's API has two tiers: the standard API available on paid plans, and the more comprehensive Kombat and historical data endpoints available on higher plans. The free trial account offers limited API lookups — enough for testing the integration but not production use. SpyFu's pricing is more affordable than SEMrush or Ahrefs for pure competitor intelligence: Basic plans start around $39/mo with API access. Review the API documentation at api.spyfu.com for the specific endpoints available on your plan. The core endpoints used in this guide — domain organic keywords, domain paid keywords, and domain overview — are available on all paid plans. SpyFu's API returns JSON directly, making it considerably easier to work with than SEMrush's semicolon-delimited CSV format. Base URL is https://api.spyfu.com.

Bolt.new Prompt

Set up SpyFu API integration. Create a .env file with SPYFU_API_KEY=your_key_here. Create lib/spyfu.ts that exports a callSpyfuAPI function which takes a URL path and params object, constructs a request to https://api.spyfu.com with HTTP Basic Auth (key as username, empty password) using Authorization header, and returns the parsed JSON response.

Paste this in Bolt.new chat

lib/spyfu.ts
1// lib/spyfu.ts
2const SPYFU_BASE_URL = 'https://api.spyfu.com';
3
4export async function callSpyfuAPI(
5 path: string,
6 params: Record<string, string | number> = {}
7): Promise<any> {
8 const apiKey = process.env.SPYFU_API_KEY;
9 if (!apiKey) {
10 throw new Error('SPYFU_API_KEY environment variable is not set');
11 }
12
13 // HTTP Basic Auth: key as username, empty password
14 const credentials = Buffer.from(`${apiKey}:`).toString('base64');
15
16 const url = new URL(`${SPYFU_BASE_URL}${path}`);
17 Object.entries(params).forEach(([k, v]) => {
18 url.searchParams.set(k, String(v));
19 });
20
21 const response = await fetch(url.toString(), {
22 headers: {
23 Authorization: `Basic ${credentials}`,
24 Accept: 'application/json',
25 },
26 });
27
28 if (!response.ok) {
29 const error = await response.text();
30 throw new Error(`SpyFu API error ${response.status}: ${error}`);
31 }
32
33 return response.json();
34}

Pro tip: SpyFu uses standard HTTP Basic Auth with the API key as the username and an empty password. The Buffer.from().toString('base64') encoding handles this correctly in Node.js. In Next.js API routes, Buffer is available natively without any imports.

Expected result: The SpyFu API utility is configured. The lib/spyfu.ts module handles authentication transparently — API route code can call callSpyfuAPI without worrying about auth headers.

2

Fetch Competitor Organic Keywords

Build the API route that retrieves organic keyword data for any domain. SpyFu's domain organic keywords endpoint returns keywords the domain ranks for in Google Search, including the current rank, estimated monthly search volume, estimated monthly clicks the domain receives from that keyword, and click-through rate. The data is paginated — use the pageSize and startingRow parameters to implement paging in the UI if you need more than the default 10 results. One important detail about SpyFu's domain format: unlike some APIs that accept bare domains like 'example.com', SpyFu's API may require the domain without 'www' prefix. Strip both protocol (https://) and www. from user input before calling the API. SpyFu also has country-specific data — the countryCode parameter accepts two-letter codes like 'US', 'UK', 'CA'. Defaulting to 'US' works for most use cases. The results drive the core competitive intelligence use case: which keywords is the competitor getting organic clicks from, ranked by traffic contribution.

Bolt.new Prompt

Create a Next.js API route at app/api/spyfu/organic-keywords/route.ts. Accept 'domain' and optional 'countryCode' (default 'US') query params. Use callSpyfuAPI from lib/spyfu.ts to fetch from /organic/v2/domain/keywords with domain, countryCode, and pageSize=20. Return a JSON array with keyword, rank, monthlySearches, monthlyClicks, clickThruRate fields mapped from the SpyFu response.

Paste this in Bolt.new chat

app/api/spyfu/organic-keywords/route.ts
1// app/api/spyfu/organic-keywords/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { callSpyfuAPI } from '@/lib/spyfu';
4
5export async function GET(request: NextRequest) {
6 const domain = request.nextUrl.searchParams.get('domain');
7 const countryCode = request.nextUrl.searchParams.get('countryCode') ?? 'US';
8
9 if (!domain) {
10 return NextResponse.json({ error: 'domain is required' }, { status: 400 });
11 }
12
13 // Strip protocol and www
14 const cleanDomain = domain
15 .replace(/^https?:\/\//, '')
16 .replace(/^www\./, '')
17 .replace(/\/$/, '')
18 .toLowerCase();
19
20 try {
21 const data = await callSpyfuAPI('/organic/v2/domain/keywords', {
22 domain: cleanDomain,
23 countryCode,
24 pageSize: 20,
25 startingRow: 1,
26 });
27
28 const keywords = (data?.results ?? []).map((item: any) => ({
29 keyword: item.term ?? '',
30 rank: item.rank ?? 0,
31 monthlySearches: item.localMonthlySearches ?? 0,
32 monthlyClicks: item.monthlyClicks ?? 0,
33 clickThruRate: item.domainClickThruRate ?? 0,
34 }));
35
36 return NextResponse.json({ domain: cleanDomain, countryCode, keywords });
37 } catch (error) {
38 const message = error instanceof Error ? error.message : 'Unknown error';
39 return NextResponse.json({ error: message }, { status: 500 });
40 }
41}

Pro tip: SpyFu's results are sorted by estimated monthly clicks by default, not by rank. This means the first result is the keyword driving the most estimated organic traffic, not the one with the best ranking — which is usually more useful for competitive analysis.

Expected result: Calling /api/spyfu/organic-keywords?domain=competitor.com returns the top 20 keywords the domain ranks for, sorted by estimated monthly traffic contribution.

3

Add PPC Keyword and Ad Copy Data

SpyFu's PPC data is one of its strongest differentiators. The paid keywords endpoint shows which keywords a domain has bid on, their estimated monthly ad spend for each keyword, how many months the keyword has been in their campaign (longer = higher confidence it converts), and the total estimated monthly PPC budget. The ad copy endpoint returns actual ad text samples — headline, display URL, and description — that the competitor has run, along with the date range the ad was active. This data is invaluable for PPC teams: a keyword a competitor has bid on for 24+ consecutive months is almost certainly profitable for them, making it a high-priority target. Ad copy samples reveal messaging strategies and value propositions that competitors have tested and kept running. The implementation follows the same proxy pattern. Note that historical PPC data depth varies by SpyFu plan — lower plans may have shorter history windows. The response structure for PPC endpoints mirrors the organic keywords structure, making the parsing code nearly identical.

Bolt.new Prompt

Add a paid keywords API route at app/api/spyfu/paid-keywords/route.ts that fetches the top 10 paid keywords for a domain using the SpyFu /paid/v2/domain/keywords endpoint. Return keyword, estimatedMonthlyBudget, monthsBidding, averageCPC, and adStrength for each keyword. Also add an app/api/spyfu/domain-overview/route.ts that returns total organic keywords, paid keywords, domain strength, and estimated monthly cost.

Paste this in Bolt.new chat

app/api/spyfu/paid-keywords/route.ts
1// app/api/spyfu/paid-keywords/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { callSpyfuAPI } from '@/lib/spyfu';
4
5export async function GET(request: NextRequest) {
6 const domain = request.nextUrl.searchParams.get('domain');
7 const countryCode = request.nextUrl.searchParams.get('countryCode') ?? 'US';
8
9 if (!domain) {
10 return NextResponse.json({ error: 'domain is required' }, { status: 400 });
11 }
12
13 const cleanDomain = domain
14 .replace(/^https?:\/\//, '')
15 .replace(/^www\./, '')
16 .replace(/\/$/, '')
17 .toLowerCase();
18
19 try {
20 const data = await callSpyfuAPI('/paid/v2/domain/keywords', {
21 domain: cleanDomain,
22 countryCode,
23 pageSize: 10,
24 startingRow: 1,
25 });
26
27 const keywords = (data?.results ?? []).map((item: any) => ({
28 keyword: item.term ?? '',
29 monthlyBudget: item.monthlyBudget ?? 0,
30 monthsBidding: item.monthsSearched ?? 0,
31 averageCPC: item.cpc ?? 0,
32 adStrength: item.strength ?? 0,
33 }));
34
35 return NextResponse.json({ domain: cleanDomain, keywords });
36 } catch (error) {
37 const message = error instanceof Error ? error.message : 'Unknown error';
38 return NextResponse.json({ error: message }, { status: 500 });
39 }
40}

Pro tip: Sort paid keywords by monthsBidding descending to surface the most persistently bid-on keywords first. A competitor bidding on a keyword for 18+ months is a strong signal that keyword converts profitably for them.

Expected result: The paid keywords route returns competitor PPC data. Keywords bid on for many months appear at the top when sorted by monthsBidding, highlighting the most valuable competitor ad spend insights.

4

Deploy to Netlify or Bolt Cloud

SpyFu API calls work in Bolt's WebContainer during development — outbound HTTPS requests to api.spyfu.com succeed because all outbound HTTP traffic is supported. Test a few domain lookups in the preview to confirm data returns correctly before deploying. When you're satisfied the integration works, deploy via Netlify (Settings → Applications → connect OAuth → click Publish) or Bolt Cloud (Publish button → top right). After deploying, add `SPYFU_API_KEY` to your hosting platform's environment variables. Netlify: Site Configuration → Environment Variables → Add variable. Bolt Cloud: use the Secrets panel. After adding the variable, trigger a fresh deploy. The dashboard should work identically on the deployed URL. Important WebContainer limitation for context: since Bolt's preview cannot receive incoming connections, you cannot register SpyFu alert webhooks to a Bolt preview URL. SpyFu doesn't currently offer webhook delivery for most data endpoints (they're primarily a query-on-demand API), but if you add any alert-style features in the future, those require a deployed stable URL. The production deployment also enables HTTPS, which is required for any OAuth-based features you might add later.

Bolt.new Prompt

Add an export to CSV button to my SpyFu competitor analysis dashboard. When clicked, download all visible competitor keywords as a CSV file named competitor-keywords-{domain}-{date}.csv using the browser's download API.

Paste this in Bolt.new chat

components/ExportButton.tsx
1// components/ExportButton.tsx
2'use client';
3
4interface ExportButtonProps {
5 data: Record<string, unknown>[];
6 filename: string;
7}
8
9export default function ExportButton({ data, filename }: ExportButtonProps) {
10 const exportCSV = () => {
11 if (data.length === 0) return;
12 const headers = Object.keys(data[0]).join(',');
13 const rows = data.map((row) =>
14 Object.values(row)
15 .map((v) => (typeof v === 'string' && v.includes(',') ? `"${v}"` : v))
16 .join(',')
17 );
18 const csv = [headers, ...rows].join('\n');
19 const blob = new Blob([csv], { type: 'text/csv' });
20 const url = URL.createObjectURL(blob);
21 const a = document.createElement('a');
22 a.href = url;
23 a.download = filename;
24 a.click();
25 URL.revokeObjectURL(url);
26 };
27
28 return (
29 <button onClick={exportCSV} disabled={data.length === 0}>
30 Export {data.length} rows as CSV
31 </button>
32 );
33}

Pro tip: The CSV export runs entirely client-side using the Blob and URL.createObjectURL APIs — no server call needed. This keeps your SpyFu API credits from being consumed again for the same data just because the user wants a download.

Expected result: After deploying, the dashboard is accessible at a public URL with SPYFU_API_KEY configured. The export button downloads competitor keyword data as a CSV file.

Common use cases

Competitor Organic Keyword Spy

Enter a competitor's domain and see every keyword they rank for organically with their current position, estimated monthly search volume, and ranking trend over time. Marketing teams use this to identify content gap opportunities — topics the competitor owns that your site hasn't covered yet.

Bolt.new Prompt

Build a competitor keyword spy tool using SpyFu API. Create a domain search form. On submit, call /api/spyfu/organic-keywords with the domain. Display the top 20 organic keywords showing keyword, rank, search volume, monthly clicks, and whether ranking has improved or declined. Use green/red arrows to show ranking trend direction.

Copy this prompt to try it in Bolt.new

PPC Ad History Analyzer

Reveal a competitor's Google Ads history — which keywords they've bid on, their estimated monthly spend, the ad copy they've tested, and which campaigns they've run consistently versus briefly. PPC teams use this to identify proven converting keywords and messaging that competitors have validated over time.

Bolt.new Prompt

Create a PPC competitor analysis page using SpyFu API. For any domain, show their top 10 paid keywords with estimated CPC, monthly budget, and how many months they've been bidding on each keyword. Also show their best-performing ad copy examples. Proxy all calls through /api/spyfu/paid-keywords. Highlight keywords they've bid on for 12+ months as 'proven converters'.

Copy this prompt to try it in Bolt.new

Domain Comparison Dashboard

Compare two or three domains side by side across organic visibility, paid advertising investment, number of keywords ranked, and estimated traffic. Useful for agency pitch decks comparing a prospect's SEO performance against competitors to demonstrate opportunity gaps.

Bolt.new Prompt

Build a domain comparison tool using SpyFu API. Let me enter two domains side by side. For each domain, fetch organic keyword count, paid keyword count, estimated monthly organic clicks, estimated monthly PPC budget, and domain strength score. Show results in a comparison table with the stronger metric highlighted in each row.

Copy this prompt to try it in Bolt.new

Troubleshooting

API returns 401 Unauthorized

Cause: The SPYFU_API_KEY environment variable is missing or contains extra whitespace. HTTP Basic Auth requires the exact key value with no extra characters.

Solution: Verify the .env file has the correct key with no leading or trailing spaces. In production, check that the variable is set in the hosting dashboard and the site has been redeployed after adding it. Confirm you're using the SpyFu API key specifically, not your SpyFu account password.

typescript
1// Trim the API key to prevent whitespace issues
2const apiKey = process.env.SPYFU_API_KEY?.trim();
3if (!apiKey) throw new Error('SPYFU_API_KEY not set');
4const credentials = Buffer.from(`${apiKey}:`).toString('base64');

Results array is empty even for well-known domains

Cause: The domain format includes protocol (https://) or www prefix that SpyFu doesn't accept, or the country code doesn't match where the domain has traffic.

Solution: Strip the protocol and www prefix before sending to the API. Also try different countryCode values — a US company might have most traffic indexed under 'US', but trying 'UK' for a British company often yields results where 'US' shows nothing.

typescript
1const cleanDomain = domain
2 .replace(/^https?:\/\//, '')
3 .replace(/^www\./, '')
4 .replace(/\/$/, '')
5 .toLowerCase();

HTTP Basic Auth fails with 'Buffer is not defined' in the API route

Cause: The code is running in an Edge Runtime context where Node.js Buffer is not available. This happens if the API route has a runtime declaration set to 'edge'.

Solution: Remove the edge runtime declaration from the API route. SpyFu API calls should use the default Node.js runtime in Next.js, not the Edge Runtime, because Buffer is required for Basic Auth encoding.

typescript
1// Remove this from your API route if present:
2// export const runtime = 'edge';
3
4// Alternative Base64 encoding without Buffer (works in Edge Runtime):
5const credentials = btoa(`${apiKey}:`);

Best practices

  • Always use a server-side Next.js API route for SpyFu calls — HTTP Basic Auth credentials are trivially decoded from base64 and must never appear in browser-accessible code
  • Clean domain input by stripping protocols, www prefixes, and trailing slashes before calling the API to avoid empty result sets
  • Cache competitor analysis results for 24-48 hours — SpyFu's database updates weekly, not in real time, so frequent polling wastes API credits
  • Sort paid keywords by monthsBidding descending to surface the most consistently profitable competitor keywords first
  • Use the countryCode parameter to match data to the user's target market — 'US' is the default but other markets require explicit country codes
  • Add pagination controls when displaying large keyword sets — SpyFu paginates results and each page costs API credits, so only load additional pages on user request
  • Highlight keywords where monthsBidding exceeds 12 months as 'proven converters' — this is SpyFu's most actionable competitive intelligence signal

Alternatives

Frequently asked questions

Does SpyFu have a free API tier?

SpyFu offers limited free lookups on their website, but API access with programmatic queries requires a paid subscription. The Basic plan (~$39/mo) includes API access for standard keyword and domain queries. The amount of free data visible on SpyFu's website is handled through their web interface, not available via the API without a subscription.

What makes SpyFu different from SEMrush for competitor research?

SpyFu's primary differentiator is historical depth and affordability. It shows competitor PPC ad history going back over a decade, revealing which keywords competitors have consistently bid on versus briefly tested. SEMrush is broader — covering content tools, site audits, and social media — but SpyFu often provides better value for pure competitor keyword intelligence at a lower price.

Can SpyFu API calls work in Bolt's WebContainer preview?

Yes. The Next.js API route makes outbound HTTPS calls to api.spyfu.com, which works fine in Bolt's WebContainer. You can test domain lookups and see competitor data in the preview before deploying. The WebContainer cannot receive incoming connections, but SpyFu's query-based API doesn't require incoming webhook connections, so this limitation doesn't affect the integration.

How do I handle SpyFu showing no data for a domain I know has SEO traffic?

First check the domain format — strip protocol and www. Try different countryCode values. Very new domains (under 6 months old) may not have enough history in SpyFu's index. Some domains in SpyFu's database are indexed under different country databases than you'd expect. If the domain genuinely has minimal search visibility, SpyFu correctly shows no data.

Is SpyFu data accurate for competitor budget estimates?

SpyFu's PPC budget estimates are modeled approximations, not actual Google Ads billing data. They're useful for understanding relative scale and identifying which keywords competitors consistently invest in, but should not be treated as precise figures. The most reliable signal SpyFu provides is consistency — a keyword shown for 18+ months of bidding is a strong indicator of profitability regardless of the exact budget estimate.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.