# How OpenSEO Handles Keyword Research Using DataForSEO

> Discover how OpenSEO revolutionizes keyword research with DataForSEO API integration. Learn about its robust architecture for authentication, location normalization, billing, and error recovery.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-09-10

---

**OpenSEO performs keyword research by orchestrating requests to the DataForSEO Labs Keywords Data API through a layered architecture that handles authentication, location normalization, credit-based billing, and granular error recovery.**

OpenSEO is an open-source SEO platform that integrates deeply with DataForSEO to deliver comprehensive keyword research capabilities. The implementation spans multiple TypeScript modules in the `every-app/open-seo` repository that transform user inputs into valid API requests while automatically tracking usage costs. This article examines the exact mechanisms used to fetch, validate, and bill for keyword data.

## The DataForSEO Integration Architecture

OpenSEO’s keyword research capability is built on five logical layers that process a request from the UI to the external API and back. The flow begins when a user selects a research scope—such as domain, subdomains, subfolder, or exact URL—and submits a seed keyword.

The architecture relies on **[`src/server/lib/dataforseo/client.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.ts)** to construct authenticated requests, **[`src/shared/billing-credit-features.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/billing-credit-features.ts)** to map API endpoints to internal credit features, and **[`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts)** to normalize locale settings. Execution is managed by **[`src/server/workflows/RankCheckWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/src/server/workflows/RankCheckWorkflow.ts)**, which also handles credit deduction and error telemetry.

## Constructing Authenticated Requests

The `createDataforseoClient` function in [`src/server/lib/dataforseo/client.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.ts) handles the core communication with DataForSEO. It constructs the JSON payload required by the API, including the keyword, language, and location parameters.

Authentication uses base-64 encoding of the `email:password` combination, which is added to the HTTP headers alongside the required content-type specifications. The client supports multiple DataForSEO Labs endpoints, including `v3/dataforseo_labs/google/related_keywords/live` and the keyword suggestions endpoint, each accepting a payload with `keyword`, `language_code`, and `location_code` fields.

## Mapping Endpoints to Billing Credits

Before any HTTP request executes, OpenSEO determines the cost implications. The file **[`src/shared/billing-credit-features.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/billing-credit-features.ts)** maps each DataForSEO API path to an internal *credit feature*—specifically `keyword_research` for keyword-related endpoints.

This mapping enables automatic per-user usage tracking. When the workflow triggers a request, the system debits the appropriate number of credits from the user's balance based on the mapped feature, ensuring costs are recorded regardless of whether the request succeeds or fails.

## Validating Locations and Languages

Keyword research accuracy depends on correct geographic and linguistic targeting. The **[`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts)** module validates that the supplied domain and locale are supported by DataForSEO Labs.

This layer rejects malformed hosts or IP addresses before a request is transmitted. It translates the UI-friendly location name into the standard DataForSEO `location_code` and `language_code` parameters (for example, converting "United States" to `location_code: "us"` and `language_code: "en"`), preventing invalid API calls that would consume credits without returning data.

## Workflow Execution and Scope Filtering

The **[`src/server/workflows/RankCheckWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/src/server/workflows/RankCheckWorkflow.ts)** orchestrates the end-to-end execution of keyword research tasks. It manages the interaction between the DataForSEO client and the billing system.

For advanced filtering, **[`src/shared/researchScope.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/researchScope.ts)** defines `RESEARCH_SCOPE_FILTER_SLOTS`, which determines how many of DataForSEO’s eight available filter slots are consumed based on the chosen research scope. A subfolder scope consumes more filter slots than a domain-level scope, allowing the platform to enforce scope-based filtering constraints before sending the request.

## Handling Charged Errors and Telemetry

DataForSEO bills for certain errors—such as "Invalid Field" responses—meaning the user pays even if no data returns. OpenSEO handles this through `DataforseoChargedTaskError`, implemented in the client logic and tested in **[`src/server/lib/dataforseo/client.test.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.test.ts)**.

When a charged error occurs, the workflow still records the exact USD cost against the user’s credit balance and propagates a useful error message to the front-end. This prevents hidden over-usage while maintaining transparent billing records for both successful and failed API interactions.

## Practical Implementation Example

The following TypeScript example demonstrates fetching related keywords using the OpenSEO DataForSEO client, including error handling for billed failures:

```typescript
import { createDataforseoClient } from "@/server/lib/dataforseo/client";
import { billingCustomer } from "@/server/lib/billing";

async function fetchRelatedKeywords(seed: string) {
  const client = createDataforseoClient(billingCustomer);

  const payload = {
    keyword: seed,
    language_code: "en",
    location_code: "us",
  };

  const result = await client.keywords.relatedKeywords(payload);
  return result;
}

try {
  const data = await fetchRelatedKeywords("open source seo");
  console.log("Related keywords:", data);
} catch (e) {
  if (e instanceof DataforseoChargedTaskError) {
    console.warn("DataForSEO error (billed):", e.message);
  } else {
    console.error("Unexpected error:", e);
  }
}

```

This implementation hits the `v3/dataforseo_labs/google/related_keywords/live` endpoint and returns an array of keyword objects containing search volume, difficulty, and intent data.

## Summary

- **Request Building**: The `createDataforseoClient` function in [`client.ts`](https://github.com/every-app/open-seo/blob/main/client.ts) constructs authenticated payloads using base-64 encoded credentials and standard DataForSEO parameters.
- **Credit Mapping**: [`billing-credit-features.ts`](https://github.com/every-app/open-seo/blob/main/billing-credit-features.ts) automatically maps API endpoints to the `keyword_research` credit feature for granular usage tracking.
- **Locale Validation**: [`keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/keyword-locations.ts) ensures only valid `location_code` and `language_code` combinations are transmitted to DataForSEO.
- **Scope Management**: [`researchScope.ts`](https://github.com/every-app/open-seo/blob/main/researchScope.ts) enforces filter slot limits based on whether the user searches across domains, subdomains, subfolders, or exact URLs.
- **Error Accountability**: `DataforseoChargedTaskError` captures billed errors to ensure credit balances are accurately maintained even when API calls fail.

## Frequently Asked Questions

### How does OpenSEO authenticate with the DataForSEO API?

OpenSEO authenticates using base-64 encoding of the user's email and password combination, which is added to the HTTP headers in [`src/server/lib/dataforseo/client.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.ts). This header is included with every request to the DataForSEO Labs endpoints, ensuring secure access to the keyword data.

### What happens if a keyword research request fails?

If the failure is a "charged error"—such as an invalid field or malformed parameter—OpenSEO throws a `DataforseoChargedTaskError`. The system still debits the user's credit balance for the cost of the call and logs the exact USD amount, then surfaces a friendly error message to the UI. Uncharged errors are handled as standard exceptions without billing.

### How does OpenSEO handle different geographic markets?

The platform uses [`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts) to validate and translate user-selected locations into DataForSEO's standard `location_code` and `language_code` identifiers. This prevents invalid requests and ensures search volume and difficulty metrics reflect the intended geographic market.

### Can users filter keyword research by specific URL paths?

Yes. OpenSEO supports scope-based filtering (domain, subdomains, subfolder, or exact URL) through [`src/shared/researchScope.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/researchScope.ts). The system calculates required filter slots using `RESEARCH_SCOPE_FILTER_SLOTS` and constructs the appropriate DataForSEO payload, enabling targeted keyword discovery for specific site sections.