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
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
Get Your SpyFu API Key and Review Pricing
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.
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
1// lib/spyfu.ts2const SPYFU_BASE_URL = 'https://api.spyfu.com';34export 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 }1213 // HTTP Basic Auth: key as username, empty password14 const credentials = Buffer.from(`${apiKey}:`).toString('base64');1516 const url = new URL(`${SPYFU_BASE_URL}${path}`);17 Object.entries(params).forEach(([k, v]) => {18 url.searchParams.set(k, String(v));19 });2021 const response = await fetch(url.toString(), {22 headers: {23 Authorization: `Basic ${credentials}`,24 Accept: 'application/json',25 },26 });2728 if (!response.ok) {29 const error = await response.text();30 throw new Error(`SpyFu API error ${response.status}: ${error}`);31 }3233 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.
Fetch Competitor Organic Keywords
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.
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
1// app/api/spyfu/organic-keywords/route.ts2import { NextRequest, NextResponse } from 'next/server';3import { callSpyfuAPI } from '@/lib/spyfu';45export async function GET(request: NextRequest) {6 const domain = request.nextUrl.searchParams.get('domain');7 const countryCode = request.nextUrl.searchParams.get('countryCode') ?? 'US';89 if (!domain) {10 return NextResponse.json({ error: 'domain is required' }, { status: 400 });11 }1213 // Strip protocol and www14 const cleanDomain = domain15 .replace(/^https?:\/\//, '')16 .replace(/^www\./, '')17 .replace(/\/$/, '')18 .toLowerCase();1920 try {21 const data = await callSpyfuAPI('/organic/v2/domain/keywords', {22 domain: cleanDomain,23 countryCode,24 pageSize: 20,25 startingRow: 1,26 });2728 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 }));3536 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.
Add PPC Keyword and Ad Copy Data
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.
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
1// app/api/spyfu/paid-keywords/route.ts2import { NextRequest, NextResponse } from 'next/server';3import { callSpyfuAPI } from '@/lib/spyfu';45export async function GET(request: NextRequest) {6 const domain = request.nextUrl.searchParams.get('domain');7 const countryCode = request.nextUrl.searchParams.get('countryCode') ?? 'US';89 if (!domain) {10 return NextResponse.json({ error: 'domain is required' }, { status: 400 });11 }1213 const cleanDomain = domain14 .replace(/^https?:\/\//, '')15 .replace(/^www\./, '')16 .replace(/\/$/, '')17 .toLowerCase();1819 try {20 const data = await callSpyfuAPI('/paid/v2/domain/keywords', {21 domain: cleanDomain,22 countryCode,23 pageSize: 10,24 startingRow: 1,25 });2627 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 }));3435 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.
Deploy to Netlify or Bolt Cloud
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.
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
1// components/ExportButton.tsx2'use client';34interface ExportButtonProps {5 data: Record<string, unknown>[];6 filename: string;7}89export 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 };2728 return (29 <button onClick={exportCSV} disabled={data.length === 0}>30 Export {data.length} rows as CSV31 </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.
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.
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.
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.
1// Trim the API key to prevent whitespace issues2const 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.
1const cleanDomain = domain2 .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.
1// Remove this from your API route if present:2// export const runtime = 'edge';34// 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
SEMrush covers SEO, PPC, content, and social in one broader platform, while SpyFu focuses on delivering deeper historical competitor keyword and ad history at a lower price.
Ahrefs has stronger backlink data and organic search analysis, while SpyFu specializes in PPC competitive intelligence and ad copy history that Ahrefs doesn't provide.
Moz focuses on domain authority and link metrics rather than competitor keyword history, making it complementary to SpyFu rather than a direct alternative.
Serpstat offers keyword and PPC data at a price point between SpyFu and SEMrush, suitable for teams that need broader coverage than SpyFu provides.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation