# How to Integrate the DataForSEO API with OpenSEO for Keyword Research

> Integrate the DataForSEO API with OpenSEO for powerful keyword research. Learn the simple steps to connect your API key and unlock advanced SEO workflows.

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

---

**OpenSEO uses DataForSEO (DfS) as its underlying data provider, requiring only a base64-encoded API key in your environment variables to enable keyword research workflows through the `createDataforseoClient` factory.**

The `every-app/open-seo` repository relies on DataForSEO for all keyword research functionality. Integrating the DataForSEO API with OpenSEO involves three architectural layers: credential provisioning, a metered client wrapper, and the keyword research service. Whether you deploy the application yourself or use the hosted SaaS version, the setup process centers on providing your DfS credentials and verifying connectivity.

## Prerequisites and Credential Setup

### Creating a DataForSEO Account

Sign up at the official DataForSEO portal to generate an API key consisting of your email and password. New accounts receive **$1 in free credit**, with a minimum top-up of **$50** for continued usage.

### Configuring the API Key in OpenSEO

For self-hosted deployments, set the `DATAFORSEO_API_KEY` environment variable in your `.env` file. The value must be a **base64-encoded** string of your `email:password` credentials:

```dotenv
DATAFORSEO_API_KEY=Zm9vQGV4YW1wbGUuY29tOnBhc3N3b3Jk

```

In the hosted SaaS version, navigate to *Settings → DataForSEO* and enter your credentials; the platform stores them securely and handles all billing.

## Understanding the Three-Layer Integration Architecture

According to the source code in `every-app/open-seo`, the integration is implemented across three distinct layers:

- **Credential Setup**: Configures the DfS API key in the backend. In hosted mode, OpenSEO bills usage credits directly, while self-hosted instances pay DataForSEO directly. See [`web/content/docs/self-hosting/index.md`](https://github.com/every-app/open-seo/blob/main/web/content/docs/self-hosting/index.md).
- **Client & Metering**: The [`src/server/lib/dataforseo/client.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.ts) file lazily loads the `dataforseo-client` SDK and wraps every call with billing-credit metering via the `createDataforseoClient` factory.
- **Keyword Research Service**: Orchestrates research flows in [`src/serverFunctions/keywords.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/keywords.ts) and [`src/server/features/keywords/services/research/research.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/keywords/services/research/research.ts), handling market resolution, endpoint selection, deduplication, and caching.

## Using the Keyword Research Service

### The researchKeywords Server Function

The UI's Keyword Research page triggers the `researchKeywords` server function exported from [`src/serverFunctions/keywords.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/keywords.ts). This function validates inputs and delegates to the `KeywordResearchService.research` method, which selects the appropriate DfS source (related, suggestions, ideas, or Google Ads) and fetches rows via `fetchResearchRowsBySource`.

```ts
import { researchKeywords } from "@/serverFunctions/keywords";

await researchKeywords({
  seedKeyword: "open source seo",
  locationCode: "us",
  languageCode: "en",
  resultLimit: 30,
  mode: "auto",
});

```

### Resolving Market Location and Language

OpenSEO derives location and language codes from your project's default market. You can override these per request using the `resolveMarket` helper, which maps market codes to DataForSEO payloads as defined in [`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts).

## Direct Client Access for Custom Tools

For custom MCP agents or server-side scripts, instantiate the client directly using the factory from [`src/server/lib/dataforseo/client.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.ts):

```ts
import { createDataforseoClient } from "@/server/lib/dataforseo";
import { getCurrentCustomerContext } from "@/server/billing/subscription";

async function demo() {
  const customer = await getCurrentCustomerContext();
  const client = createDataforseoClient(customer);
  
  // Example: fetch related keywords for "open source seo"
  const related = await client.keywords.related({
    seedKeyword: "open source seo",
    locationCode: "us",
    languageCode: "en",
    resultLimit: 20,
  });
  console.log(related);
}

```

The `meter` wrapper in [`client.ts`](https://github.com/every-app/open-seo/blob/main/client.ts) automatically charges the appropriate credit feature (`"rank_tracking"` by default) against the organization's credit pool.

To fetch Google Ads keyword ideas when Labs does not support a specific location, use the client methods exposed in [`src/server/lib/dataforseo/sections.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/sections.ts):

```ts
import { createDataforseoClient } from "@/server/lib/dataforseo";
import { getOrCreateOrganizationCustomer } from "@/server/billing/subscription";

async function fetchIdeas() {
  const orgCustomer = await getOrCreateOrganizationCustomer(/* current user */);
  const client = createDataforseoClient(orgCustomer);

  const ideas = await client.keywords.adsIdeas({
    seedKeyword: "cloud hosting",
    locationCode: "ca",
    languageCode: "en",
    resultLimit: 25,
  });
  return ideas;
}

```

## Monitoring Usage and Billing

Every DataForSEO call records its USD cost in `result.billing`. The metering layer tracks spend against your organization's credit pool through the `trackUsageCreditSpend` mechanism. Hosted deployments view remaining credits in the *Billing* dashboard, while self-hosted deployments receive invoices directly from DataForSEO.

You can verify your API key connectivity by running the built-in health check (`whoami` tool) or hitting the `/api/_internal/selfhost-check` route.

## Summary

- OpenSEO requires a **base64-encoded** `DATAFORSEO_API_KEY` in your environment for self-hosted setups.
- The integration uses a three-layer architecture: credentials, the metered `createDataforseoClient`, and the `KeywordResearchService`.
- Use `researchKeywords` from [`src/serverFunctions/keywords.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/keywords.ts) for standard UI workflows.
- Direct client instantiation allows custom tools to access DataForSEO endpoints with automatic billing metering.
- Location and language mappings are handled in [`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts).

## Frequently Asked Questions

### What is the minimum credit requirement for DataForSEO?

New DataForSEO accounts receive $1 in free credit upon signup. To continue using the service beyond the trial, you must top up your balance with a minimum of $50.

### How does OpenSEO handle billing differently in self-hosted versus hosted mode?

In self-hosted deployments of `every-app/open-seo`, you pay DataForSEO directly for API usage. In the hosted SaaS version, OpenSEO bills you for usage credits internally and manages the DataForSEO relationship on your behalf.

### Where does keyword deduplication and caching occur?

The `KeywordResearchService.research` method in [`src/server/features/keywords/services/research/research.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/keywords/services/research/research.ts) handles deduplication and caching after fetching raw data from DataForSEO endpoints.

### Can I override the default market location for specific keyword queries?

Yes. While OpenSEO defaults to your project's market settings, you can specify custom `locationCode` and `languageCode` parameters in the `researchKeywords` call or use the `resolveMarket` helper defined in [`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts) to map custom markets.