To integrate Replit with SpyFu, sign up for a SpyFu API plan, get your API key from the account settings, store it in Replit Secrets (lock icon π), and use Python or Node.js to fetch competitor keyword rankings, PPC ad history, and organic search data. Deploy on Autoscale for on-demand competitive intelligence queries.
Why Connect Replit to the SpyFu API?
SpyFu is one of the most detailed competitor intelligence tools available, offering over 14 years of historical keyword and PPC data for millions of domains. Unlike broader SEO suites, SpyFu's core differentiator is its focus on competitor analysis β understanding exactly which keywords competitors rank for organically, which Google Ads they run, how much they spend on PPC, and how their rankings change over time. The SpyFu API exposes this data programmatically, enabling automated competitor tracking, agency reporting, and alerting workflows.
The SpyFu API is organized around domain-level queries. You supply a competitor's domain name and the API returns their organic keywords, monthly clicks, domain strength, PPC keywords, estimated ad spend, and ad copy text. This is useful for building automated competitive dashboards, generating client SEO reports, identifying keyword gaps between your site and competitors, and monitoring when competitors change their PPC strategy.
SpyFu API access requires a paid plan (Basic or higher) β the API is not available on the free tier. The API key is passed as a query parameter called 'api_key' or uses Basic auth with the key. Rate limits vary by plan. Store the key in Replit Secrets and proxy all SpyFu API calls through your Replit backend to prevent key exposure.
Integration method
You connect Replit to SpyFu by subscribing to an API-enabled SpyFu plan, obtaining your API key from account settings, and storing it in Replit Secrets. Your server-side Python or Node.js code sends requests to the SpyFu REST API with your API key as a query parameter, retrieving competitor domain data, keyword rankings, PPC spend estimates, and ad copy history. SpyFu API access is included with paid plans β there is no free API tier.
Prerequisites
- A Replit account with a Python or Node.js project created
- A SpyFu paid plan (Basic or higher) with API access enabled at https://www.spyfu.com
- An API key from SpyFu account settings under API & Integrations
- Basic understanding of SEO metrics (organic keywords, SERP ranking, PPC spend)
- Familiarity with making HTTP GET requests in Python (requests library) or Node.js (axios)
Step-by-step guide
Get Your SpyFu API Key
Get Your SpyFu API Key
Log into your SpyFu account at https://www.spyfu.com and navigate to Account Settings. Look for the API section or 'API Access' β the location varies slightly by plan. If you are on the Basic plan or higher with API access enabled, your API key is displayed in this section as a long alphanumeric string. SpyFu does not offer a free API tier. If you are on the free plan, you will need to upgrade to at least the Basic plan ($39/month as of 2026) to get API access. The API is included in paid plans without an additional fee, though rate limits apply β typically 500 requests per day on the Basic plan and higher limits on Team/Agency plans. SpyFu also supports Basic auth for API requests, where your username is your API key and the password is 'X' (a placeholder). This alternative authentication method works the same as the query parameter method. For this tutorial, we use the query parameter approach as it is simpler. The SpyFu API documentation is available at https://www.spyfu.com/api β review the available endpoints before building your integration. Key endpoints include /core/v2/domains/stats (domain overview), /core/v2/domains/organic_keywords (top organic keywords), and /core/v2/domains/ppc_keywords (PPC keywords).
Pro tip: SpyFu API access is included with paid plans β check your current plan level. If you need API access for evaluation, start a trial of the Basic plan.
Expected result: You have a SpyFu API key from your account settings page.
Store the API Key in Replit Secrets
Store the API Key in Replit Secrets
Open your Replit project and click the lock icon π in the left sidebar. Add a new secret: - Key: SPYFU_API_KEY - Value: your SpyFu API key Click 'Add Secret' to save. Access the key in Python with os.environ['SPYFU_API_KEY'] and in Node.js with process.env.SPYFU_API_KEY. SpyFu API keys are tied to your account and its subscription. Exposing the key could allow others to consume your API quota or access competitive data billed to your account. Replit's encrypted Secrets pane keeps the key out of your source code and prevents it from being accidentally committed to GitHub.
Pro tip: If you are building a multi-client agency tool, all clients share your single SpyFu API key β plan your rate limit budget accordingly across all client queries.
Expected result: SPYFU_API_KEY appears in the Replit Secrets pane with its value hidden.
Query SpyFu Competitor Data with Python
Query SpyFu Competitor Data with Python
Install requests with 'pip install requests flask'. The SpyFu API uses simple GET requests with query parameters including 'api_key', 'q' (the domain to analyze), 'pageSize', and 'startingRow' for pagination. The Flask server below provides three endpoints: /domain-stats for a domain overview (estimated monthly clicks, organic keywords count, PPC keywords count, monthly ad budget), /organic-keywords for the top ranking keywords, and /ppc-keywords for paid search keywords with estimated costs. Note that SpyFu data is estimated from their proprietary model β treat all numbers as approximations rather than exact figures. The data is most reliable for larger domains with significant traffic history in SpyFu's dataset.
1import os2import requests3from flask import Flask, request, jsonify45app = Flask(__name__)67SPYFU_API_KEY = os.environ["SPYFU_API_KEY"]8BASE_URL = "https://www.spyfu.com/apis/core_api/v2"91011def spyfu_get(endpoint: str, params: dict) -> dict:12 """Make a GET request to the SpyFu API."""13 params["api_key"] = SPYFU_API_KEY14 resp = requests.get(f"{BASE_URL}{endpoint}", params=params)15 resp.raise_for_status()16 return resp.json()171819@app.route("/domain-stats")20def domain_stats():21 """Get high-level SEO and PPC stats for a domain."""22 domain = request.args.get("domain")23 if not domain:24 return jsonify({"error": "domain parameter required"}), 40025 try:26 data = spyfu_get("/domains/stats", {"q": domain})27 return jsonify(data)28 except requests.HTTPError as e:29 return jsonify({"error": str(e)}), e.response.status_code if e.response else 500303132@app.route("/organic-keywords")33def organic_keywords():34 """Get top organic keywords for a domain."""35 domain = request.args.get("domain")36 page_size = int(request.args.get("page_size", 20))37 starting_row = int(request.args.get("starting_row", 0))38 if not domain:39 return jsonify({"error": "domain parameter required"}), 40040 try:41 data = spyfu_get("/domains/organic_keywords", {42 "q": domain,43 "pageSize": min(page_size, 100),44 "startingRow": starting_row,45 "sortBy": "monthly_clicks",46 "sortOrder": "descending"47 })48 return jsonify(data)49 except requests.HTTPError as e:50 return jsonify({"error": str(e)}), e.response.status_code if e.response else 500515253@app.route("/ppc-keywords")54def ppc_keywords():55 """Get PPC keywords and ad data for a domain."""56 domain = request.args.get("domain")57 page_size = int(request.args.get("page_size", 20))58 starting_row = int(request.args.get("starting_row", 0))59 if not domain:60 return jsonify({"error": "domain parameter required"}), 40061 try:62 data = spyfu_get("/domains/ppc_keywords", {63 "q": domain,64 "pageSize": min(page_size, 100),65 "startingRow": starting_row,66 "sortBy": "monthly_clicks",67 "sortOrder": "descending"68 })69 return jsonify(data)70 except requests.HTTPError as e:71 return jsonify({"error": str(e)}), e.response.status_code if e.response else 500727374@app.route("/competitor-report")75def competitor_report():76 """Generate a combined organic + PPC report for a domain."""77 domain = request.args.get("domain")78 if not domain:79 return jsonify({"error": "domain parameter required"}), 40080 try:81 stats = spyfu_get("/domains/stats", {"q": domain})82 organic = spyfu_get("/domains/organic_keywords", {83 "q": domain, "pageSize": 10, "startingRow": 0,84 "sortBy": "monthly_clicks", "sortOrder": "descending"85 })86 ppc = spyfu_get("/domains/ppc_keywords", {87 "q": domain, "pageSize": 10, "startingRow": 0,88 "sortBy": "monthly_clicks", "sortOrder": "descending"89 })90 return jsonify({91 "domain": domain,92 "stats": stats,93 "top_organic_keywords": organic.get("results", []),94 "top_ppc_keywords": ppc.get("results", [])95 })96 except requests.HTTPError as e:97 return jsonify({"error": str(e)}), e.response.status_code if e.response else 5009899100if __name__ == "__main__":101 app.run(host="0.0.0.0", port=3000, debug=True)Pro tip: Use the 'sortBy=monthly_clicks&sortOrder=descending' parameters to get the most impactful keywords first β these are the ones driving the most traffic for the competitor.
Expected result: GET /competitor-report?domain=example.com returns a JSON object with domain stats, top organic keywords, and top PPC keywords.
Build a Node.js SpyFu Integration
Build a Node.js SpyFu Integration
Install dependencies with 'npm install express axios'. The Node.js version uses axios for HTTP requests and provides the same endpoint structure as the Python version. The server below adds a /keyword-competitors endpoint that takes a keyword (rather than a domain) and returns the top domains ranking organically and running PPC ads for that keyword. This is useful for keyword-first competitor analysis: find who else is targeting a keyword you care about.
1const express = require('express');2const axios = require('axios');34const app = express();5app.use(express.json());67const SPYFU_API_KEY = process.env.SPYFU_API_KEY;8const BASE_URL = 'https://www.spyfu.com/apis/core_api/v2';910async function spyfuGet(endpoint, params = {}) {11 const { data } = await axios.get(`${BASE_URL}${endpoint}`, {12 params: { ...params, api_key: SPYFU_API_KEY }13 });14 return data;15}1617// Domain overview stats18app.get('/domain-stats', async (req, res) => {19 const { domain } = req.query;20 if (!domain) return res.status(400).json({ error: 'domain parameter required' });21 try {22 const data = await spyfuGet('/domains/stats', { q: domain });23 res.json(data);24 } catch (err) {25 res.status(err.response?.status || 500).json({ error: err.response?.data || err.message });26 }27});2829// Top organic keywords30app.get('/organic-keywords', async (req, res) => {31 const { domain, page_size = 20, starting_row = 0 } = req.query;32 if (!domain) return res.status(400).json({ error: 'domain parameter required' });33 try {34 const data = await spyfuGet('/domains/organic_keywords', {35 q: domain,36 pageSize: Math.min(Number(page_size), 100),37 startingRow: Number(starting_row),38 sortBy: 'monthly_clicks',39 sortOrder: 'descending'40 });41 res.json(data);42 } catch (err) {43 res.status(err.response?.status || 500).json({ error: err.response?.data || err.message });44 }45});4647// PPC keywords48app.get('/ppc-keywords', async (req, res) => {49 const { domain, page_size = 20, starting_row = 0 } = req.query;50 if (!domain) return res.status(400).json({ error: 'domain parameter required' });51 try {52 const data = await spyfuGet('/domains/ppc_keywords', {53 q: domain,54 pageSize: Math.min(Number(page_size), 100),55 startingRow: Number(starting_row),56 sortBy: 'monthly_clicks',57 sortOrder: 'descending'58 });59 res.json(data);60 } catch (err) {61 res.status(err.response?.status || 500).json({ error: err.response?.data || err.message });62 }63});6465// Keyword-based competitor lookup66app.get('/keyword-competitors', async (req, res) => {67 const { keyword, page_size = 10 } = req.query;68 if (!keyword) return res.status(400).json({ error: 'keyword parameter required' });69 try {70 const data = await spyfuGet('/keywords/organic_competitors', {71 q: keyword,72 pageSize: Math.min(Number(page_size), 50)73 });74 res.json(data);75 } catch (err) {76 res.status(err.response?.status || 500).json({ error: err.response?.data || err.message });77 }78});7980app.listen(3000, '0.0.0.0', () => {81 console.log('SpyFu integration server running on port 3000');82});Pro tip: The /keyword-competitors endpoint is useful for keyword research β it shows which domains are already ranking for your target keyword, letting you gauge competition level before investing in SEO or PPC.
Expected result: GET /organic-keywords?domain=competitor.com returns a JSON object with the competitor's top organic keywords sorted by estimated monthly clicks.
Deploy and Schedule Competitor Monitoring
Deploy and Schedule Competitor Monitoring
Click the Deploy button in Replit and choose Autoscale for an on-demand competitive intelligence API. If you want to schedule regular competitor checks (e.g., weekly reports), use a Scheduled deployment instead, which runs your script on a cron-like schedule without needing an external scheduler. For a scheduled monitoring script, create a main function that runs the competitor analysis for your tracked domains, formats the results, and sends the report by email or posts it to a Slack channel. The Replit Scheduled deployment type runs the script at your configured interval and stops it when done. After deploying, verify your API key is accessible in the production environment by checking that the first SpyFu request succeeds. Review SpyFu API rate limits in your account plan to ensure your scheduled queries stay within daily limits.
1[[ports]]2internalPort = 30003externalPort = 8045[deployment]6run = ["node", "server.js"]7deploymentTarget = "cloudrun"Pro tip: SpyFu data updates weekly for most domains. Running more than one competitive analysis per day per domain is unlikely to show new data and wastes API quota.
Expected result: Your deployed Replit app serves SpyFu competitive intelligence queries at the production URL with the API key securely stored in Secrets.
Common use cases
Automated Competitor Keyword Report
A Replit backend queries SpyFu weekly for the top organic and PPC keywords of a list of competitor domains, compares the results to the previous week, and sends a summary email highlighting new keywords, dropped rankings, and PPC budget changes. This automates a manual competitor analysis process that would otherwise take hours.
Build a Python script that queries SpyFu for the top 50 organic keywords of three competitor domains, identifies keywords that overlap across all three, and outputs a CSV report sorted by estimated monthly clicks.
Copy this prompt to try it in Replit
PPC Gap Analysis Tool
A Replit API endpoint accepts a client's domain and their top competitor's domain, queries SpyFu for keywords each domain is bidding on, and returns a list of keywords the competitor bids on that the client does not. This PPC gap analysis helps agencies quickly identify paid search opportunities for their clients.
Create a Flask endpoint that accepts two domains, fetches their PPC keywords from SpyFu, and returns the keywords appearing in the competitor's paid campaigns but not in the client's, sorted by competitor estimated monthly ad clicks.
Copy this prompt to try it in Replit
Domain SEO Snapshot Dashboard
A Replit web app provides an internal dashboard where a marketing team can enter any competitor domain and instantly see key SpyFu metrics: estimated organic monthly clicks, number of ranking keywords, estimated PPC monthly spend, and top-performing ad copy examples. This replaces manual lookups in the SpyFu web UI.
Write an Express server with a /domain-report route that accepts a domain parameter, queries multiple SpyFu endpoints, and returns a consolidated JSON report with organic rank data and PPC metrics in a single response.
Copy this prompt to try it in Replit
Troubleshooting
HTTP 403 Forbidden when calling the SpyFu API
Cause: API access is not enabled on your current SpyFu plan, or the API key is incorrect or has been regenerated.
Solution: Log into SpyFu and verify your plan includes API access. Check the Account Settings > API section for the current API key β if the key was regenerated, update SPYFU_API_KEY in Replit Secrets. Free plan users must upgrade to Basic or higher.
Empty results array for a domain that clearly exists
Cause: SpyFu may not have sufficient data for the domain queried. Small or new domains with low traffic often appear in SpyFu but return empty keyword arrays because SpyFu has not accumulated enough data.
Solution: Try a well-known domain (e.g., 'amazon.com') to confirm the API is working. For small domains, SpyFu may return stats fields with zero values. Check the 'totalAvailableResults' field in the response β if it is zero, SpyFu has no data for that domain.
1# Check if data exists before processing2if data.get('totalAvailableResults', 0) == 0:3 return jsonify({'message': 'No SpyFu data available for this domain', 'results': []})Rate limit errors after running many domain queries
Cause: SpyFu API rate limits vary by plan. Running bulk analysis across many domains in rapid succession can exhaust daily request quotas.
Solution: Add a short delay between API calls in batch processing scripts. Cache domain results for at least 24 hours since SpyFu data updates weekly. Check your SpyFu account for current API usage to see how much quota remains.
1import time23domains = ['competitor1.com', 'competitor2.com', 'competitor3.com']4for domain in domains:5 data = spyfu_get('/domains/stats', {'q': domain})6 # process data7 time.sleep(1) # 1 second between requestsSPYFU_API_KEY is undefined or None in the running server
Cause: The Replit Secret was added after the server started running, or the variable name in Secrets does not exactly match what the code references.
Solution: Restart the Repl after adding a new secret. Check that the key name in Replit Secrets is exactly SPYFU_API_KEY (case-sensitive). Use os.environ.get('SPYFU_API_KEY', 'missing') to detect missing secrets early during startup.
1SPYFU_API_KEY = os.environ.get('SPYFU_API_KEY')2if not SPYFU_API_KEY:3 raise ValueError('SPYFU_API_KEY secret is missing. Add it in Replit Secrets.')Best practices
- Store SPYFU_API_KEY in Replit Secrets (lock icon π) and never include it in client-side JavaScript or API responses.
- Cache SpyFu domain results for at least 24 hours β data updates weekly, so repeated queries for the same domain within a day return identical results and waste API quota.
- Always check totalAvailableResults before processing domain data β small or new domains may return zero results.
- Use pageSize and startingRow parameters for pagination when analyzing large keyword datasets rather than requesting all data in a single call.
- Treat all SpyFu traffic and spend estimates as approximations β they are modeled from SpyFu's proprietary data and should be used for directional analysis, not as exact figures.
- Deploy on Autoscale for interactive competitor lookups or Scheduled deployment for automated weekly reports β avoid Reserved VM for this use case.
- Track multiple competitors over time by storing results in a database rather than fetching fresh data every time β this enables trend analysis across weeks and months.
- Include the domain's SpyFu page URL (https://www.spyfu.com/overview/domain?query={domain}) in your reports so stakeholders can click through to full SpyFu UI for deeper analysis.
Alternatives
SEMrush offers a broader digital marketing toolkit including social media, content marketing, and site audit features alongside competitive intelligence, making it a better choice when SEO is just one part of your marketing stack.
Ahrefs is the strongest tool for backlink analysis and link building research, making it a better fit when competitor link profiles matter more than PPC spend intelligence.
Serpstat offers similar competitor intelligence at a lower price point with a more accessible API, making it a better choice for budget-conscious teams or agencies managing many client domains.
Frequently asked questions
How do I get a SpyFu API key?
Log into your SpyFu account and navigate to Account Settings, then look for the API or Integrations section. Your API key is displayed there. SpyFu API access is included with paid plans (Basic and above) β free accounts do not have API access.
Is the SpyFu API available on the free plan?
No. SpyFu API access requires a paid subscription (Basic plan or higher). If you are on the free tier, you can only view data through the SpyFu web interface. Upgrade your plan in SpyFu account settings to unlock API access.
How accurate is SpyFu data for competitor analysis?
SpyFu data is estimated from their proprietary model that analyzes billions of search results over time. Traffic and spend figures are approximations that are typically accurate within an order of magnitude for larger domains. Small or new domains may have limited or missing data. Use SpyFu for directional competitive intelligence rather than precise measurement.
Can I use SpyFu to track multiple competitors automatically in Replit?
Yes. Build a Python or Node.js script that iterates over a list of competitor domains, queries SpyFu for each, and stores results in a database or exports to a spreadsheet. Schedule the script using Replit's Scheduled deployment type to run weekly. Cache results to avoid redundant API calls since SpyFu data updates at most weekly.
What is the difference between SpyFu and SEMrush for API access?
SpyFu specializes in competitor PPC and organic search intelligence with deep historical ad data, while SEMrush offers a broader API covering keyword research, site audit, social tracking, and more. SpyFu is better for teams focused specifically on competitor PPC analysis; SEMrush is better when you need a comprehensive digital marketing data API.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation