
Security News
Open VSX Unblocks Extension IDs Used in Malware Campaign
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.
@power-seo/integrations
Advanced tools
Third-party SEO tool API clients for Semrush and Ahrefs with shared HTTP client
Typed Semrush and Ahrefs API clients for keyword research, domain overviews, backlinks, and keyword difficulty — built on a shared rate-limited HTTP client with automatic retry.
@power-seo/integrations is a TypeScript client library for the Semrush and Ahrefs SEO data APIs, aimed at developers building keyword research pipelines, backlink monitors, and SEO reporting tools in Node.js. Both clients share one HTTP layer — createHttpClient() — that enforces a token-bucket rate limit, retries retryable failures with exponential backoff, and normalizes every non-2xx response into a single IntegrationApiError with status, provider, and retryable fields. Every request parameter and response field is fully typed, so keyword volume, CPC, Domain Rating, and backlink data arrive as structured objects instead of hand-parsed payloads.
Network access note — this package's documented purpose is calling external APIs. HTTPS requests go exclusively to the endpoints you configure (
api.semrush.com,api.ahrefs.com, or your ownbaseUrl), authenticated with your credentials. Nothing else is contacted.
| Without | With | |
|---|---|---|
| Semrush API | ❌ Hand-write requests, parse column codes | ✅ Typed client — Or/Nq/Kd mapped to named fields |
| Ahrefs API | ❌ Manual bearer auth and query building | ✅ Typed client with token auth handled for you |
| Rate limiting | ❌ Manual throttle or 429 storms | ✅ Built-in token bucket (default 600 requests/minute) |
| Retry logic | ❌ Ad-hoc try/catch loops | ✅ Exponential backoff on 429/5xx, up to 3 retries by default |
| Pagination | ❌ Untyped offset bookkeeping | ✅ PaginatedResponse<T> with offset, limit, hasMore |
| Error handling | ❌ Raw HTTP errors, secrets leaking into logs | ✅ IntegrationApiError with sanitized, token-redacted body |
| TypeScript types | ❌ any everywhere | ✅ Full type coverage for every endpoint and response |
| Bundle size | ❌ Full vendor SDK in your bundle | ✅ Tree-shakeable — import only the client you use |
createHttpClient() works against any JSON REST API with query-param or bearer auth, a configurable per-minute rate limit, request timeout, and retryrateLimitPerMinutemaxRetries times with delays of 1s, 2s, 4s… capped at 30sPaginatedResponse<T> with data, total, offset, limit, and hasMore for clean cursor loopscreateSemrushClient, createAhrefsClient, and createHttpClient are independent named exports| Feature | @power-seo/integrations | Hand-rolled fetch wrapper | Calling vendor endpoints directly |
|---|---|---|---|
| Typed Semrush responses | ✅ | Manual | ❌ (column codes) |
| Typed Ahrefs responses | ✅ | Manual | ❌ (raw JSON) |
| Rate limiting | ✅ token bucket | Manual | ❌ |
| Retry with backoff | ✅ 429/5xx aware | Manual | ❌ |
| Consistent errors across vendors | ✅ IntegrationApiError | Manual | ❌ |
| Secret redaction in errors | ✅ | Rarely | ❌ |
| One HTTP layer for both APIs | ✅ | ❌ | ❌ |
| Tree-shakeable TypeScript | ✅ | — | — |
npm install @power-seo/integrations
yarn add @power-seo/integrations
pnpm add @power-seo/integrations
Requires Node.js 18+ (native fetch). Also runs in Deno, Bun, and edge runtimes that provide fetch, URL, and AbortController.
Create a client with createSemrushClient(apiKey, config?) — the first argument is your Semrush API key as a plain string (sent as the key query parameter), and the optional second argument tunes rateLimitPerMinute, maxRetries, and timeoutMs. The client exposes five typed methods covering domain overview, organic keywords, backlinks, keyword difficulty, and related keywords. Regional database defaults to 'us' and list endpoints default to 100 rows per page.
import { createSemrushClient } from '@power-seo/integrations';
import type { SemrushDomainOverview } from '@power-seo/integrations';
const semrush = createSemrushClient(process.env.SEMRUSH_API_KEY!, {
rateLimitPerMinute: 60, // optional — default 600
});
// Domain overview — traffic, keywords, backlinks, Authority Score
const overview: SemrushDomainOverview = await semrush.getDomainOverview('example.com', 'us');
// { domain, organicKeywords, organicTraffic, organicCost, paidKeywords,
// paidTraffic, paidCost, backlinks, authorityScore }
// Organic keywords (paginated)
const keywords = await semrush.getOrganicKeywords('example.com', { limit: 100, offset: 0 });
// { data: SemrushKeywordData[], total, offset, limit, hasMore }
// Backlinks (paginated)
const backlinks = await semrush.getBacklinks('example.com', { limit: 100, offset: 0 });
// Keyword difficulty for a batch of keywords
const difficulty = await semrush.getKeywordDifficulty(['react seo', 'next.js seo'], 'us');
// [{ keyword, difficulty, searchVolume, cpc, competition, results }]
// Related keyword suggestions
const related = await semrush.getRelatedKeywords('react seo', 'us');
// [{ keyword, searchVolume, cpc, competition, results, relatedTo }]
Create a client with createAhrefsClient(apiToken, config?) — the first argument is your Ahrefs API token as a plain string, sent as an Authorization: Bearer header to api.ahrefs.com/v3. The client covers site overview, organic keywords, backlinks, keyword difficulty, and referring domains. List endpoints accept { limit, offset } and default to 100 rows per page.
import { createAhrefsClient } from '@power-seo/integrations';
import type { AhrefsSiteOverview } from '@power-seo/integrations';
const ahrefs = createAhrefsClient(process.env.AHREFS_API_TOKEN!);
// Site overview — DR, UR, traffic, traffic value
const site: AhrefsSiteOverview = await ahrefs.getSiteOverview('example.com');
// { domain, domainRating, urlRating, backlinks, referringDomains,
// organicKeywords, organicTraffic, trafficValue }
// Organic keywords with positions (paginated)
const keywords = await ahrefs.getOrganicKeywords('example.com', { limit: 200, offset: 0 });
// Backlinks with anchor text and dofollow status (paginated)
const backlinks = await ahrefs.getBacklinks('example.com', { limit: 100 });
// data[i]: { sourceUrl, targetUrl, anchorText, domainRating, urlRating,
// isDoFollow, firstSeen, lastSeen }
// Keyword difficulty for a batch of keywords
const kd = await ahrefs.getKeywordDifficulty(['react seo']);
// [{ keyword, difficulty, searchVolume, cpc, clicks, globalVolume }]
// Referring domains (paginated)
const domains = await ahrefs.getReferringDomains('example.com', { limit: 50 });
Every list endpoint returns a PaginatedResponse<T> carrying the page you asked for plus the cursor state: data (the rows), total (as reported by the API), and offset, limit, hasMore. hasMore is true while a page comes back full, so a simple loop that advances offset by limit walks the entire result set.
import type { SemrushKeywordData } from '@power-seo/integrations';
const all: SemrushKeywordData[] = [];
let offset = 0;
let hasMore = true;
while (hasMore) {
const page = await semrush.getOrganicKeywords('example.com', { limit: 100, offset });
all.push(...page.data);
offset += page.limit;
hasMore = page.hasMore;
}
createHttpClient(config) is exported directly, so the same rate limiting, timeout, retry, and error normalization work against any JSON REST API. Pass a baseUrl, an auth strategy (bearer header or query parameter), and optional limits. get() appends query params; post() JSON-encodes the body. Both return the parsed JSON typed as your generic parameter.
import { createHttpClient } from '@power-seo/integrations';
const http = createHttpClient({
baseUrl: 'https://api.example.com',
auth: { type: 'bearer', token: process.env.API_TOKEN! },
rateLimitPerMinute: 60, // default 600
maxRetries: 3, // default 3
timeoutMs: 30_000, // default 30_000
});
const result = await http.get<{ items: string[] }>('/endpoint', { q: 'seo' });
const created = await http.post<{ id: string }>('/endpoint', { name: 'report' });
Every non-2xx response becomes an IntegrationApiError with status (HTTP status code), provider ('semrush', 'ahrefs', or 'unknown'), and retryable (true for 429 and 5xx). Retryable errors are retried automatically with exponential backoff (1s, 2s, 4s… capped at 30s) up to maxRetries times before being thrown; non-retryable errors (4xx other than 429) throw immediately. Error messages embed a sanitized response snippet — bearer tokens and API keys are redacted and the snippet is truncated to 200 characters.
import { createSemrushClient, IntegrationApiError } from '@power-seo/integrations';
const semrush = createSemrushClient(process.env.SEMRUSH_API_KEY!);
try {
const data = await semrush.getDomainOverview('example.com');
} catch (err) {
if (err instanceof IntegrationApiError) {
console.error(`${err.provider} API error ${err.status}: ${err.message}`);
console.error('Retryable:', err.retryable); // true for 429 / 5xx
} else {
throw err; // network failure or abort — propagated without retry
}
}
createSemrushClient(apiKey, config?)function createSemrushClient(
apiKey: string,
config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,
): SemrushClient;
Targets https://api.semrush.com with query-parameter auth (key).
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getDomainOverview | (domain, database?) | Promise<SemrushDomainOverview> | database defaults to 'us' |
getOrganicKeywords | (domain, options?) | Promise<PaginatedResponse<SemrushKeywordData>> | limit defaults to 100 |
getBacklinks | (domain, options?) | Promise<PaginatedResponse<SemrushBacklinkData>> | Root-domain backlink profile |
getKeywordDifficulty | (keywords[], database?) | Promise<SemrushKeywordDifficulty[]> | Batch lookup, one row per keyword |
getRelatedKeywords | (keyword, database?) | Promise<SemrushRelatedKeyword[]> | Related keyword suggestions |
createAhrefsClient(apiToken, config?)function createAhrefsClient(
apiToken: string,
config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,
): AhrefsClient;
Targets https://api.ahrefs.com/v3 with Authorization: Bearer auth.
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getSiteOverview | (domain) | Promise<AhrefsSiteOverview> | DR, UR, traffic, traffic value |
getOrganicKeywords | (domain, options?) | Promise<PaginatedResponse<AhrefsOrganicKeyword>> | limit defaults to 100 |
getBacklinks | (domain, options?) | Promise<PaginatedResponse<AhrefsBacklink>> | Anchor text + dofollow status |
getKeywordDifficulty | (keywords[]) | Promise<AhrefsKeywordDifficulty[]> | Batch lookup |
getReferringDomains | (domain, options?) | Promise<PaginatedResponse<AhrefsReferringDomain>> | Referring domains with DR |
createHttpClient(config)function createHttpClient(config: HttpClientConfig): HttpClient;
HttpClient has two methods: get<T>(path, params?) and post<T>(path, body?).
HttpClientConfig| Prop | Type | Default | Description |
|---|---|---|---|
baseUrl | string | required | Base URL prepended to every request path |
auth | AuthStrategy | required | bearer header or query parameter credential |
rateLimitPerMinute | number | 600 | Token-bucket capacity; requests wait for a token |
maxRetries | number | 3 | Retries after the first attempt (429/5xx only) |
timeoutMs | number | 30000 | Per-request timeout enforced via AbortController |
AuthStrategy is one of:
{ type: 'bearer', token: string } — sent as an Authorization: Bearer header{ type: 'query', paramName: string, value: string } — appended as a query parameterIntegrationApiError| Property | Type | Description |
|---|---|---|
message | string | Provider, status, and a sanitized response snippet |
status | number | HTTP status code of the failed response |
provider | string | 'semrush', 'ahrefs', or 'unknown' |
retryable | boolean | true when status === 429 or status >= 500 |
All exported types, importable with import type:
import type {
// HTTP layer
AuthStrategy,
HttpClientConfig,
HttpClient,
PaginatedResponse,
// Semrush
SemrushClient,
SemrushPaginationOptions, // { limit?, offset?, database? }
SemrushDomainOverview,
SemrushKeywordData,
SemrushBacklinkData,
SemrushKeywordDifficulty,
SemrushRelatedKeyword,
// Ahrefs
AhrefsClient,
AhrefsPaginationOptions, // { limit?, offset? }
AhrefsSiteOverview,
AhrefsOrganicKeyword,
AhrefsBacklink,
AhrefsKeywordDifficulty,
AhrefsReferringDomain,
} from '@power-seo/integrations';
PaginatedResponse<T> is { data: T[]; total: number; offset: number; limit: number; hasMore: boolean }. The IntegrationApiError class is a value export: import { IntegrationApiError } from '@power-seo/integrations'.
@power-seo/content-analysis scoring@power-seo/analytics and @power-seo/search-consolecreateHttpClient() for internal or third-party JSON APIs that need throttling and retry@power-seo/core only — the token bucket (createTokenBucket), backoff (calculateBackoff), and retry loop (fetchJsonWithRetry) come from the core package; nothing third-partyfetch transport — works in Node.js 18+, Deno, Bun, Cloudflare Workers, and Vercel Edge; timeouts use AbortControllerOr, Nq, Kd; Ahrefs snake_case fields) to stable camelCase types; the HTTP concerns live in one placesideEffects: false, separate named exports, built with tsupgithub.com/CyberCraftBD/power-seo GitHub Actions workflow, so you can trace each tarball back to its exact source commit@power-seo packages, nothing else gets pulled inpostinstall, preinstall)eval or dynamic code executionAll 17 packages are independently installable — use only what you need.
| Package | Install | Description |
|---|---|---|
@power-seo/ai | npm i @power-seo/ai | LLM-agnostic prompt templates and response parsers for AI-assisted SEO |
@power-seo/analytics | npm i @power-seo/analytics | Merge Search Console data with audit results — trends and ranking insights |
@power-seo/audit | npm i @power-seo/audit | SEO site health auditing with meta, content, structure, and performance rules |
@power-seo/content-analysis | npm i @power-seo/content-analysis | Yoast-style SEO content analysis engine with scoring, checks, and React components |
@power-seo/core | npm i @power-seo/core | Framework-agnostic SEO analysis engines, types, validators, and utilities |
@power-seo/images | npm i @power-seo/images | Image SEO analysis — alt text quality, lazy loading, formats, image sitemaps |
@power-seo/integrations | npm i @power-seo/integrations | Semrush and Ahrefs API clients with a shared rate-limited HTTP client |
@power-seo/links | npm i @power-seo/links | Internal link graph analysis — orphan detection, suggestions, equity scoring |
@power-seo/meta | npm i @power-seo/meta | SSR meta tag helpers for Next.js App Router, Remix v2, and generic SSR |
@power-seo/preview | npm i @power-seo/preview | SERP, Open Graph, and Twitter Card preview generators with React components |
@power-seo/react | npm i @power-seo/react | React SEO components — meta tags, Open Graph, Twitter Card, breadcrumbs |
@power-seo/readability | npm i @power-seo/readability | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI |
@power-seo/redirects | npm i @power-seo/redirects | Redirect rule engine with Next.js, Remix, and Express adapters |
@power-seo/schema | npm i @power-seo/schema | Type-safe JSON-LD structured data — 23 schema.org builders plus React components |
@power-seo/search-console | npm i @power-seo/search-console | Google Search Console API client — OAuth2, service accounts, rate limiting, retry |
@power-seo/sitemap | npm i @power-seo/sitemap | XML sitemap generation, streaming, and validation with image, video, news support |
@power-seo/tracking | npm i @power-seo/tracking | Analytics script builders with consent management and React components |
semrush api, ahrefs api, seo api client, keyword research api, backlink api, domain overview, keyword difficulty, keyword volume, rate limiting, token bucket, api pagination, typescript seo, seo data fetching, third-party seo integrations, referring domains, organic keywords, api retry backoff, seo reporting
CyberCraft Bangladesh is a Bangladesh-based enterprise-grade software development and Full Stack SEO service provider company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies.
© 2026 CyberCraft Bangladesh · Released under the MIT License
FAQs
Third-party SEO tool API clients for Semrush and Ahrefs with shared HTTP client
We found that @power-seo/integrations demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.

Product
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.

Product
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.