DataForSEO
Category: SEO & Research
Integration type: Platform-level API (single account, shared across tenants)
External API: DataForSEO REST API v3
Purpose
DataForSEO provides SERP data, backlink status checks, and keyword difficulty at competitive API pricing. Unlike SEMrush (which tenants configure individually), DataForSEO is a platform-level integration — a single platform account serves all tenants. Usage is metered per-tenant and factored into platform operating costs.
Key uses:
- Backlink Researcher — bulk backlink existence checks via DataForSEO’s Backlinks API
- Site Auditor — on-demand SERP position checks for tracked keywords
- Content Brief Writer — SERP analysis to identify top-ranking content structure for a keyword
Config Structure
Platform config (env vars)
DATAFORSEO_LOGIN=your@email.com
DATAFORSEO_PASSWORD=your_api_password
DATAFORSEO_BASE_URL=https://api.dataforseo.com/v3DataForSEO uses HTTP Basic Auth, not API keys. The login/password pair is the DataForSEO account credentials.
Integration Pattern
Tool layer (packages/tools/src/dataforseo.ts)
DataForSEO uses an asynchronous task model for some endpoints (post task → poll for results). The platform uses live endpoints where available to avoid polling complexity:
class DataForSEOTool {
private auth: string;
constructor(login: string, password: string, private baseUrl: string) {
this.auth = Buffer.from(`${login}:${password}`).toString('base64');
}
private headers() {
return {
Authorization: `Basic ${this.auth}`,
'Content-Type': 'application/json',
};
}
// SERP — Get top 10 results for a keyword
async getSerpResults(
keyword: string,
location: string = 'United States',
language: string = 'English',
): Promise<SerpResult[]> {
const response = await axios.post(
`${this.baseUrl}/serp/google/organic/live/advanced`,
[{ keyword, location_name: location, language_name: language, depth: 10 }],
{ headers: this.headers() },
);
const task = response.data.tasks[0];
if (task.status_code !== 20000) {
throw new DataForSEOError(task.status_code, task.status_message);
}
return task.result[0].items.map((item: any) => ({
position: item.rank_absolute,
url: item.url,
title: item.title,
snippet: item.description,
}));
}
// Backlinks — Check if a URL has a backlink from a specific domain
async checkBacklink(
target: string, // The page being linked to
from: string, // The linking domain to check
): Promise<BacklinkCheckResult> {
const response = await axios.post(
`${this.baseUrl}/backlinks/backlinks/live`,
[{
target,
filters: ['domain_from', '=', from],
limit: 1,
}],
{ headers: this.headers() },
);
const task = response.data.tasks[0];
const items = task.result[0]?.items ?? [];
return {
found: items.length > 0,
backlink: items[0] ?? null,
};
}
// Keyword Difficulty — batch check for a list of keywords
async getKeywordDifficulty(
keywords: string[],
location: string = 'United States',
): Promise<KeywordDifficultyResult[]> {
const response = await axios.post(
`${this.baseUrl}/keywords_data/google/search_volume/live`,
keywords.map(keyword => ({
keyword,
location_name: location,
language_name: 'English',
})),
{ headers: this.headers() },
);
return response.data.tasks.map((task: any) => ({
keyword: task.result[0].keyword,
searchVolume: task.result[0].search_volume,
competition: task.result[0].competition, // 0–1 float
cpc: task.result[0].cpc,
}));
}
}Backlink status tracking
DataForSEO is used to verify backlinks after outreach. When the Backlink Researcher delivers a prospect list and outreach emails are sent, a periodic DataForSEO check (backlink_checks table) verifies whether the link has been placed:
// Scheduled job — runs daily
for (const prospect of pendingOutreach) {
const result = await dataForSEO.checkBacklink(prospect.targetUrl, prospect.prospectDomain);
await db.update(backlinks)
.set({
status: result.found ? 'live' : 'pending',
lastChecked: new Date(),
})
.where(eq(backlinks.id, prospect.backlinkId));
}API Pricing
DataForSEO charges per task result item. Approximate costs:
| Endpoint | Cost |
|---|---|
| SERP live/advanced (10 results) | $0.0075 per task |
| Backlinks live (1 result) | $0.002 per result |
| Search volume live (1 keyword) | $0.0005 per keyword |
Platform operating costs from DataForSEO are factored into the credit pricing, not charged separately to tenants.
Test Cases
Unit tests (packages/tools/src/dataforseo.test.ts)
| Test | Approach |
|---|---|
getSerpResults() sends correct Basic Auth header | Mock axios.post; assert Authorization: Basic ... |
getSerpResults() parses top 10 items correctly | Feed mock tasks[0].result[0].items; assert positions and URLs |
getSerpResults() throws on non-20000 status code | Mock status_code: 40101; assert DataForSEOError thrown |
checkBacklink() returns found: true when items present | Mock response with 1 backlink item |
checkBacklink() returns found: false when empty | Mock items: [] |
getKeywordDifficulty() batches all keywords in one request | Assert request body has one item per keyword |
Integration tests
| Test | Approach |
|---|---|
| SERP results for known keyword | Use test credentials; fetch react testing library; assert ≥1 result |
| Backlink check for known link | Check a known public backlink; assert found: true |
Related
- SEMrush Provider — keyword research (tenant-configured)
- Backlink Researcher Agent — primary consumer of DataForSEO backlinks
- Site Auditor Agent — SERP position consumer
- Tool Integration Layer — tool registration