To integrate Replit with Serpstat, store your Serpstat API token in Replit Secrets (lock icon π), then call the Serpstat REST API from your Node.js or Python backend to retrieve SERP positions, keyword data, and competitor analysis. Serpstat is an affordable all-in-one SEO platform covering keyword research, rank tracking, backlink analysis, and site audits. Deploy as Autoscale for on-demand SEO data endpoints.
Build SEO Data Pipelines with Replit and Serpstat
Serpstat is an affordable alternative to SEMrush and Ahrefs that covers the full SEO workflow: keyword research, SERP analysis, competitor intelligence, backlink data, and technical audits. Its API gives programmatic access to the same data powering the web interface, making it well-suited for building custom SEO dashboards, automated rank tracking reports, and content opportunity pipelines on top of Replit.
The Serpstat API uses a straightforward token-based authentication model β your token is a query parameter appended to every request. This simplicity makes it easy to get started quickly, but it also means the token must never appear in client-side code. Your Replit backend acts as a proxy, receiving requests from your frontend or internal tools, calling Serpstat server-side, and returning only the data your application needs.
Practical use cases range from automating weekly ranking reports (pull position data for a list of target keywords and email a digest) to building competitive intelligence tools that surface new opportunities when a competitor's domain gains rankings. Serpstat's API pricing is usage-based on top of the subscription tier, so implementing a caching layer in your Replit app prevents redundant API calls and keeps costs predictable.
Integration method
Serpstat exposes a JSON REST API that accepts your API token as a query parameter on every request. Your Replit backend calls Serpstat endpoints to retrieve keyword metrics, SERP results, domain analytics, and competitor data. Because the API token is sensitive, all requests must originate from your Replit server β never from the browser directly. The API returns structured JSON with SEO data that your backend can transform, cache, and serve to your application.
Prerequisites
- A Replit account with a Node.js or Python Repl ready
- A Serpstat account with API access enabled (available on paid plans)
- Your Serpstat API token from Account Settings > API
- Basic understanding of REST APIs and JSON
- Familiarity with SEO concepts like SERP positions and keyword volume
Step-by-step guide
Get Your Serpstat API Token and Add it to Replit Secrets
Get Your Serpstat API Token and Add it to Replit Secrets
Log into your Serpstat account at serpstat.com and navigate to Account Settings by clicking your profile avatar in the top-right corner. In the settings panel, find the 'API' section. Your API token is displayed there β click 'Copy' to copy it to your clipboard. If you do not see an API section, your current Serpstat plan may not include API access; check the Serpstat pricing page for plans that include API credits. In Replit, click the lock icon (π) in the left sidebar to open the Secrets pane. Add one secret: SERPSTAT_API_TOKEN: your full API token string. Serpstat's API uses the token as a query parameter β every request URL ends with ?token=YOUR_TOKEN. Your Replit backend reads the token from process.env.SERPSTAT_API_TOKEN (Node.js) or os.environ['SERPSTAT_API_TOKEN'] (Python) and appends it at request time. Never construct URLs with the token from the browser side. Serpstat API calls are billed in credits based on your subscription. Check your remaining API credits in the Account > API section before building high-volume pipelines. The API endpoint is https://api.serpstat.com/v4 and accepts GET requests with query parameters. Default rate limits are generous for typical usage but the API returns 429 if you send too many requests per second.
1// test-serpstat.js β Verify Serpstat API token2const axios = require('axios');34const SERPSTAT_TOKEN = process.env.SERPSTAT_API_TOKEN;5const API_BASE = 'https://api.serpstat.com/v4';67async function testConnection() {8 // Get user info to verify token9 const resp = await axios.get(`${API_BASE}/`, {10 params: {11 token: SERPSTAT_TOKEN,12 method: 'SerpstatApiV2.getStats'13 }14 });15 const data = resp.data;16 if (data.error) {17 throw new Error(`Serpstat API error: ${data.error.message}`);18 }19 console.log('Serpstat connection OK');20 console.log('API credits remaining:', data.result?.credits_left ?? 'N/A');21}2223testConnection().catch(err => {24 console.error('Connection test failed:', err.message);25 if (!process.env.SERPSTAT_API_TOKEN) {26 console.error('SERPSTAT_API_TOKEN not found. Add it to Replit Secrets (lock icon π).');27 }28});Pro tip: Serpstat API credits are consumed per data row returned, not per API call. A request for 1,000 keywords consumes 1,000 credits. Set limits on your queries (use the 'size' parameter) to control credit consumption, especially during development.
Expected result: The test script prints 'Serpstat connection OK' and displays your remaining API credits, confirming the token is valid.
Query Domain Keyword Rankings and SERP Data
Query Domain Keyword Rankings and SERP Data
The core Serpstat API method for domain SEO analysis is SerpstatApiV2.getDomainKeywords. This returns the organic keywords a domain ranks for in a given search engine (e.g., Google US = 'g_us'), along with position, URL, search volume, and CPC data for each keyword. Requests to the Serpstat API use a method-based routing model: you pass the method name as a query parameter, along with the domain or keyword you want to analyze and the search engine database to query. Serpstat covers multiple Google regional databases (g_us, g_uk, g_de, etc.) and Yandex, so always specify the se (search engine) parameter matching your target market. The API returns a result object with an array of keyword data items and paging metadata. The default page size is 100 rows β for large domains with thousands of ranking keywords, you will need to paginate using the page parameter. Each keyword item includes: keyword, position, url, volume (monthly search volume), cpc (cost per click), difficulty, and traffic_percent (estimated share of organic traffic from that keyword). For Python projects, the requests library handles this cleanly with the params dict. For Node.js, axios params object appends them as query parameters automatically. Implement a simple in-memory cache (or write results to a JSON file) to avoid re-querying Serpstat for the same domain/keyword within a short time window.
1# serpstat_domain.py β Query domain keywords from Serpstat (Python)2import os3import requests4from flask import Flask, request, jsonify56API_BASE = 'https://api.serpstat.com/v4'7SERPSTAT_TOKEN = os.environ['SERPSTAT_API_TOKEN']89def get_domain_keywords(domain, search_engine='g_us', page=1, size=100):10 """Retrieve organic keywords a domain ranks for."""11 resp = requests.get(API_BASE, params={12 'token': SERPSTAT_TOKEN,13 'method': 'SerpstatApiV2.getDomainKeywords',14 'query': domain,15 'se': search_engine,16 'page': page,17 'size': size18 })19 resp.raise_for_status()20 data = resp.json()21 if 'error' in data:22 raise ValueError(f"Serpstat error: {data['error']['message']}")23 return data.get('result', {})2425def get_domain_overview(domain, search_engine='g_us'):26 """Get top-level domain metrics: visibility, traffic, keyword count."""27 resp = requests.get(API_BASE, params={28 'token': SERPSTAT_TOKEN,29 'method': 'SerpstatApiV2.getDomainInfo',30 'query': domain,31 'se': search_engine32 })33 resp.raise_for_status()34 data = resp.json()35 if 'error' in data:36 raise ValueError(f"Serpstat error: {data['error']['message']}")37 return data.get('result', {})3839app = Flask(__name__)4041@app.route('/api/domain/overview')42def domain_overview():43 domain = request.args.get('domain')44 if not domain:45 return jsonify({'error': 'domain parameter required'}), 40046 try:47 data = get_domain_overview(domain)48 return jsonify({49 'domain': domain,50 'keywords': data.get('keywords', 0),51 'traffic': data.get('traff', 0),52 'visibility': data.get('visible', 0)53 })54 except Exception as e:55 return jsonify({'error': str(e)}), 5005657@app.route('/api/domain/keywords')58def domain_keywords():59 domain = request.args.get('domain')60 if not domain:61 return jsonify({'error': 'domain parameter required'}), 40062 try:63 result = get_domain_keywords(domain, size=50)64 keywords = result.get('data', [])65 return jsonify({'domain': domain, 'count': len(keywords), 'keywords': keywords})66 except Exception as e:67 return jsonify({'error': str(e)}), 5006869if __name__ == '__main__':70 app.run(host='0.0.0.0', port=3000)Pro tip: Always pass a specific 'size' parameter to limit results per call. Serpstat charges per row returned, so a query without a size limit can unexpectedly drain your monthly API credit balance on domains with large keyword portfolios.
Expected result: GET /api/domain/overview?domain=example.com returns keyword count, traffic estimate, and visibility score. GET /api/domain/keywords?domain=example.com returns the top 50 ranking keywords with positions and volumes.
Keyword Research and Suggestions
Keyword Research and Suggestions
Beyond domain analysis, Serpstat's keyword API methods let you research new keyword opportunities. SerpstatApiV2.getKeywordInfo returns search volume, CPC, competition level, and related keyword count for a specific keyword. SerpstatApiV2.getKeywordTopUrls returns the top-ranking URLs for a keyword β useful for understanding what content type Google favors for a given query. For keyword expansion, SerpstatApiV2.getKeywordSuggestions returns related keywords grouped by semantic similarity. This is the programmatic equivalent of Serpstat's web interface 'Related keywords' feature. Each suggestion includes estimated monthly search volume, keyword difficulty score (0-100), and CPC data. All keyword methods use the same API endpoint with different method names and the query parameter set to your keyword instead of a domain. The search engine parameter (se) determines which Google regional database to pull from β always match this to your target audience's location. For a keyword research pipeline, combine getKeywordInfo (to validate existing target keywords) with getKeywordSuggestions (to expand your list), then filter by difficulty < 40 and volume > 100 to surface achievable opportunities. Write results to a CSV using Node.js csv-writer or Python's built-in csv module for team review.
1// keyword-research.js β Keyword research via Serpstat API (Node.js)2const axios = require('axios');34const API_BASE = 'https://api.serpstat.com/v4';5const TOKEN = process.env.SERPSTAT_API_TOKEN;67async function getKeywordInfo(keyword, searchEngine = 'g_us') {8 const resp = await axios.get(API_BASE, {9 params: {10 token: TOKEN,11 method: 'SerpstatApiV2.getKeywordInfo',12 query: keyword,13 se: searchEngine14 }15 });16 const data = resp.data;17 if (data.error) throw new Error(data.error.message);18 return data.result;19}2021async function getKeywordSuggestions(keyword, searchEngine = 'g_us', size = 50) {22 const resp = await axios.get(API_BASE, {23 params: {24 token: TOKEN,25 method: 'SerpstatApiV2.getKeywordSuggestions',26 query: keyword,27 se: searchEngine,28 size29 }30 });31 const data = resp.data;32 if (data.error) throw new Error(data.error.message);33 return data.result?.data || [];34}3536async function findOpportunities(seedKeyword) {37 console.log(`\nAnalyzing seed keyword: "${seedKeyword}"`);3839 const info = await getKeywordInfo(seedKeyword);40 console.log(`Volume: ${info.volume}, Difficulty: ${info.difficulty}, CPC: $${info.cost}`);4142 const suggestions = await getKeywordSuggestions(seedKeyword, 'g_us', 100);43 const opportunities = suggestions44 .filter(k => k.difficulty < 40 && k.volume > 100)45 .sort((a, b) => b.volume - a.volume)46 .slice(0, 10);4748 console.log(`\nTop 10 low-difficulty opportunities (difficulty < 40, volume > 100):`);49 opportunities.forEach(k => {50 console.log(` "${k.keyword}" β vol: ${k.volume}, difficulty: ${k.difficulty}`);51 });5253 return opportunities;54}5556findOpportunities('replit tutorial').catch(console.error);Pro tip: The Serpstat keyword difficulty score is on a 0-100 scale. Keywords under 30 are generally achievable for newer sites; 30-60 requires established authority; above 60 is highly competitive. Use difficulty filtering to surface realistic targets before investing in content creation.
Expected result: The script prints search volume and difficulty for the seed keyword, then lists the top 10 related keywords with low difficulty and meaningful search volume β actionable content opportunities.
Build a Cached SEO Data API
Build a Cached SEO Data API
Serpstat API credits are finite and shared across your team. Building a caching layer in your Replit backend prevents redundant calls β once you have fetched keyword data for a domain, cache it for a defined TTL (time-to-live) before querying Serpstat again. For in-process caching, use a simple JavaScript Map or Python dictionary with TTL tracking. For persistent caching across restarts, write results to a JSON file in your Replit project. For production-grade caching, use Redis (via Upstash or a Redis cloud service) to share the cache across multiple Replit instances in an Autoscale deployment. Expose a simple REST API from your Replit backend that wraps Serpstat calls with cache-aside logic: check the cache first, return the cached response if fresh, otherwise call Serpstat, update the cache, and return the result. Include a Cache-Control header in your API responses so your frontend also caches results appropriately. Set the TTL based on how often the data changes β keyword volume and positions change slowly, so a 24-hour cache is usually appropriate. Competitor data might be cached for even longer (weekly). This approach means your app's users get fast responses, your credit balance stays predictable, and Serpstat's rate limits are not a concern.
1// cached-seo-api.js β Serpstat with in-memory caching (Node.js Express)2const axios = require('axios');3const express = require('express');45const API_BASE = 'https://api.serpstat.com/v4';6const TOKEN = process.env.SERPSTAT_API_TOKEN;78// Simple in-memory cache with TTL9const cache = new Map();10const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours1112function getCached(key) {13 const entry = cache.get(key);14 if (!entry) return null;15 if (Date.now() - entry.timestamp > CACHE_TTL_MS) {16 cache.delete(key);17 return null;18 }19 return entry.data;20}2122function setCached(key, data) {23 cache.set(key, { data, timestamp: Date.now() });24}2526async function serpstatRequest(method, params) {27 const cacheKey = `${method}:${JSON.stringify(params)}`;28 const cached = getCached(cacheKey);29 if (cached) {30 console.log(`Cache HIT: ${cacheKey}`);31 return cached;32 }3334 console.log(`Cache MISS: calling Serpstat for ${method}`);35 const resp = await axios.get(API_BASE, {36 params: { token: TOKEN, method, ...params }37 });38 const data = resp.data;39 if (data.error) throw new Error(data.error.message);40 setCached(cacheKey, data.result);41 return data.result;42}4344const app = express();4546app.get('/api/seo/domain', async (req, res) => {47 const { domain, se = 'g_us' } = req.query;48 if (!domain) return res.status(400).json({ error: 'domain required' });49 try {50 const result = await serpstatRequest('SerpstatApiV2.getDomainInfo', { query: domain, se });51 res.set('Cache-Control', 'public, max-age=3600');52 res.json({ domain, data: result });53 } catch (err) {54 res.status(500).json({ error: err.message });55 }56});5758app.get('/api/seo/keywords', async (req, res) => {59 const { keyword, se = 'g_us' } = req.query;60 if (!keyword) return res.status(400).json({ error: 'keyword required' });61 try {62 const result = await serpstatRequest('SerpstatApiV2.getKeywordInfo', { query: keyword, se });63 res.json({ keyword, data: result });64 } catch (err) {65 res.status(500).json({ error: err.message });66 }67});6869app.listen(3000, '0.0.0.0', () => console.log('SEO API with caching running on port 3000'));Pro tip: Note that the in-memory cache is reset every time your Replit container restarts. For a persistent cache that survives restarts, write cache entries to a JSON file with fs.writeFileSync, or use a lightweight external store like Upstash Redis.
Expected result: GET /api/seo/domain?domain=example.com returns domain SEO metrics. The second request for the same domain is served from cache with a 'Cache HIT' log message and no Serpstat API call.
Common use cases
Automated Keyword Ranking Report
Build a Replit script that queries Serpstat for the current SERP positions of a target domain for a defined keyword list, formats the results into a CSV or JSON report, and stores or emails it on a schedule. Run it weekly as a Replit Scheduled deployment to get recurring rank tracking without paying for a dedicated rank tracker tool.
Build a Python script that queries Serpstat for keyword rankings of a domain, compares positions week-over-week, and outputs a CSV report with position changes.
Copy this prompt to try it in Replit
Competitor Keyword Gap Analysis
Use the Serpstat API to pull the top-ranking keywords for a list of competitor domains, then identify keywords where competitors rank in positions 1-10 but your target domain does not appear in the top 20. Surface these gap opportunities as a prioritized list for content creation.
Create an Express endpoint that accepts a target domain and a list of competitor domains, queries Serpstat for their top keywords, and returns keywords where competitors outrank the target.
Copy this prompt to try it in Replit
SEO Monitoring Dashboard API
Build a backend API that aggregates Serpstat data β domain visibility score, estimated organic traffic, top-ranking pages, and keyword count β into a single JSON response. Front this with a simple dashboard that lets your team monitor SEO health for multiple client domains from one interface.
Build a Node.js API that fetches Serpstat domain overview data (visibility, traffic, keywords) for a given domain and returns a normalized JSON object for a monitoring dashboard.
Copy this prompt to try it in Replit
Troubleshooting
API response returns 'error' object with 'Invalid token' or 'Access denied' message
Cause: The SERPSTAT_API_TOKEN in Replit Secrets is missing, has extra whitespace, or the token has been regenerated in Serpstat's settings since it was added. Also occurs if your Serpstat plan does not include API access.
Solution: Open Replit Secrets (lock icon π) and verify SERPSTAT_API_TOKEN is present with no leading/trailing spaces. Log into Serpstat Dashboard > Account Settings > API to confirm the token matches. If your plan was changed, upgrade to a plan that includes API credits.
1// Debug: print token presence (never log the actual token value)2console.log('Token set:', !!process.env.SERPSTAT_API_TOKEN);3console.log('Token length:', (process.env.SERPSTAT_API_TOKEN || '').length);Response contains 'credits limit exceeded' or '402 Payment Required' error
Cause: Your Serpstat API credit balance for the current billing period has been exhausted. Credits are consumed per row of data returned, not per request.
Solution: Check your credit balance in Serpstat Dashboard > Account Settings > API. Reduce query sizes using the 'size' parameter to limit rows per call. Implement caching (see Step 4) to avoid re-fetching the same data. Consider upgrading your Serpstat plan if your usage is consistently high.
1// Always pass size to limit credit usage2const resp = await axios.get(API_BASE, {3 params: {4 token: TOKEN,5 method: 'SerpstatApiV2.getDomainKeywords',6 query: domain,7 se: 'g_us',8 size: 50 // Limit to 50 rows = 50 credits consumed9 }10});Empty result array or zero keywords returned for a domain that clearly has organic traffic
Cause: The search engine database parameter ('se') does not match where the domain ranks. Using 'g_us' for a domain that primarily ranks in the UK (g_uk) or Germany (g_de) will return no results.
Solution: Try different 'se' parameter values matching the domain's target market: g_uk for United Kingdom, g_au for Australia, g_de for Germany, g_fr for France. Check Serpstat's documentation for the full list of supported search engine codes.
1// Try multiple search engines if result is empty2const engines = ['g_us', 'g_uk', 'g_au'];3for (const se of engines) {4 const result = await serpstatRequest('SerpstatApiV2.getDomainKeywords', { query: domain, se, size: 10 });5 console.log(`${se}: ${result?.data?.length || 0} keywords found`);6}429 Too Many Requests error from the Serpstat API
Cause: Too many API calls are being made within a short time window. This typically happens during development when calling Serpstat in a loop without any delay.
Solution: Add a delay between requests in loops using setTimeout (Node.js) or time.sleep (Python). Implement the caching layer from Step 4 so repeated calls for the same data are served from cache rather than hitting Serpstat. For batch processing, add 1-2 seconds between each API call.
1// Add delay between batch requests to avoid rate limits2async function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }34for (const domain of domainList) {5 const data = await serpstatRequest('SerpstatApiV2.getDomainInfo', { query: domain, se: 'g_us' });6 console.log(`${domain}:`, data);7 await sleep(1500); // 1.5 second delay between requests8}Best practices
- Store SERPSTAT_API_TOKEN in Replit Secrets (lock icon π) and never include it in frontend code β all Serpstat API calls must originate from your Replit backend
- Always pass an explicit 'size' parameter to limit rows returned per call β Serpstat charges per row, and unbounded queries can exhaust your monthly credit balance unexpectedly
- Implement a cache layer (in-memory Map or file-based) with a 24-hour TTL for domain and keyword data β SEO metrics change slowly and caching prevents redundant credit consumption
- Match the 'se' (search engine) parameter to your target audience's country β using g_us for a UK-focused domain will return empty results
- Deploy as Replit Autoscale for on-demand SEO data endpoints; use a Scheduled deployment if you need automated weekly rank tracking reports
- Add retry logic with exponential backoff for 429 rate-limit responses β include a 1-2 second delay between calls in any batch processing loop
- Filter keyword results by difficulty and volume before storing or displaying them β processing all returned keywords adds computation overhead without always adding business value
- Log all Serpstat API calls with their credit cost to a database or file so you can audit usage and optimize high-cost queries
Alternatives
SEMrush has a deeper feature set and broader data coverage, making it the better choice for agencies managing many clients β but it costs significantly more than Serpstat.
Ahrefs provides the most comprehensive backlink index and is the go-to tool for link building campaigns where backlink data quality matters more than price.
Moz is best known for its Domain Authority metric, which is widely used as a standard benchmark β choose Moz if DA/PA comparisons are central to your SEO workflow.
Frequently asked questions
How do I connect Replit to Serpstat?
Add your SERPSTAT_API_TOKEN to Replit Secrets (lock icon π), then make GET requests from your Node.js or Python backend to https://api.serpstat.com/v4 with the token as a query parameter and the desired method name. The API returns JSON with SEO data that your backend can transform and serve to your application.
Does Replit work with Serpstat?
Yes. Serpstat exposes a standard REST API that any HTTP client can call. Your Replit backend (Node.js or Python) calls Serpstat server-side with your API token, keeping credentials secure. No special Serpstat SDK is needed β axios or the requests library are sufficient.
How do I store my Serpstat API token in Replit?
Click the lock icon (π) in the Replit sidebar to open Secrets, then add a secret named SERPSTAT_API_TOKEN with your token as the value. Access it in Node.js as process.env.SERPSTAT_API_TOKEN and in Python as os.environ['SERPSTAT_API_TOKEN']. Never paste the token value directly in your code files.
Can I use Serpstat in Replit for free?
Serpstat requires a paid subscription to access API features β API access is not available on the free plan. However, Replit's free tier is sufficient to build and test the integration code once you have a Serpstat paid account. Production deployments should use Replit's Autoscale deployment.
How do I avoid consuming too many Serpstat API credits?
Always pass an explicit 'size' parameter to limit rows returned per API call since Serpstat charges per row. Implement a caching layer with a 24-hour TTL so repeated requests for the same domain or keyword are served from cache. Monitor your credit balance in Serpstat Dashboard > Account Settings > API.
What is the difference between Serpstat and SEMrush for API integration?
Both provide similar keyword and domain data via REST APIs, but Serpstat is generally more affordable for solo developers and small teams. SEMrush has deeper data coverage and more endpoint types. For straightforward rank tracking and keyword research automation, Serpstat delivers good value; choose SEMrush for large-scale agency workflows needing broader data access.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation