Semrush and Ahrefs API client with rate limiting and pagination in TypeScript

1 day ago 3
ARTICLE AD BOX

I'm building an SEO reporting dashboard where I need to pull keyword data and backlink profiles from both Semrush and Ahrefs APIs. I'm running into two problems:

Both APIs have rate limits — I keep getting 429 errors when running bulk queries

Results are paginated — I have to manually track offsets and loop through pages to get complete data

What I've tried:

// Manual Semrush API call — no rate limiting, no pagination handling const response = await fetch( `https://api.semrush.com/?type=domain_organic&key=${API_KEY}&domain=example.com&limit=100` ); const text = await response.text(); // Parse CSV manually... // If I need more than 100 results, I have to manually handle pagination: let offset = 0; let allResults = []; while (true) { const res = await fetch(`...&offset=${offset}&limit=100`); const data = await res.text(); if (!data) break; allResults.push(...parse(data)); offset += 100; } // No error handling, no rate limiting, no TypeScript types

Problems with this approach:

No built-in rate limiting — hitting 429 errors under load

Manual pagination is repetitive and error-prone

Raw CSV parsing from Semrush — no typed response objects

Different auth patterns for Semrush (query param) vs Ahrefs (bearer token) — duplicating HTTP logic

What I need:

// Semrush — typed client with rate limiting

const semrush = createSemrushClient({ apiKey: process.env.SEMRUSH_API_KEY });

const overview = await semrush.getDomainOverview({ domain: 'example.com' });

console.log(overview.organicTraffic);  // 12400

console.log(overview.organicKeywords); // 834

console.log(overview.backlinks);       // 2341

// Auto-paginated keyword data — no manual offset tracking

const keywords = await semrush.getOrganicKeywords('example.com', { limit: 100 });

console.log(keywords.data);    // SemrushKeywordData[]

console.log(keywords.hasMore); // false — already fetched all pages

// Ahrefs — same pattern, different provider

const ahrefs = createAhrefsClient({ apiKey: process.env.AHREFS_API_TOKEN });

const site = await ahrefs.getSiteOverview({ target: 'example.com' });

console.log(site.domainRating);   // 47

console.log(site.organicTraffic); // 9800

const kd = await ahrefs.getKeywordDifficulty(['react seo', 'next.js seo']);

console.log(kd);

// [

//   { keyword: 'react seo', difficulty: 42, searchVolume: 1200 },

//   { keyword: 'next.js seo', difficulty: 38, searchVolume: 880 },

// ]

Error handling I need:

Read Entire Article