Connect Retool to SEMrush by creating a REST API Resource with SEMrush's API base URL and your API key as a URL parameter. Use SEMrush's API to build comprehensive SEO analytics dashboards covering domain analytics, keyword research, backlink data, and site audit results — giving your SEO and marketing ops teams direct access to all SEMrush data in a configurable internal tool.
| Fact | Value |
|---|---|
| Tool | SEMrush |
| Category | SEO |
| Method | REST API Resource |
| Difficulty | Intermediate |
| Time required | 25 minutes |
| Last updated | April 2026 |
Build an All-in-One SEMrush SEO Analytics Dashboard in Retool
SEMrush is the most comprehensive digital marketing platform available, providing organic keyword rankings, paid advertising data, backlink profiles, site audit results, competitor analysis, and more — all in one subscription. However, marketing and SEO teams often work across multiple tools simultaneously, and switching between SEMrush's various sections to compile a weekly performance report or track a competitor's moves is time-consuming.
Retool enables you to pull all the SEMrush data your team needs into a single configurable dashboard. Instead of manually pulling reports from SEMrush's interface, your ops team can build panels that show domain organic traffic trends, top-ranking keywords with position changes, new and lost backlinks, competitor comparison tables, and site audit scores — all refreshable on demand and filterable by date range, keyword type, or domain.
SEMrush's API uses a consistent pattern: API key passed as a URL parameter, report type specified in the URL path or query parameter, and response data returned as pipe-delimited text. Retool's server-side proxy keeps your API key secure, and a JavaScript transformer normalizes the pipe-delimited format into clean JSON arrays for Retool's Table and Chart components. Note that SEMrush API calls consume API units — check your subscription's monthly unit limit before building high-frequency dashboards.
Integration method
SEMrush connects to Retool through a REST API Resource using API key authentication passed as a URL parameter. All requests are proxied server-side through Retool, keeping your API key secure. You configure the base URL and API key once at the resource level, then build individual queries for each SEMrush report type — domain analytics, keyword data, backlink analysis, and site audit results — using SEMrush's reporting API endpoints.
Prerequisites
- A SEMrush account with API access enabled (available on Pro, Guru, and Business plans — not available on the free plan)
- A SEMrush API key (Account Settings → API → Generate API Key or copy existing key)
- A Retool account with permission to create Resources
- Awareness of your SEMrush API unit limit (each API call consumes units based on report type)
- Familiarity with Retool's query editor, Table component, and Chart component
Step-by-step guide
Create the SEMrush REST API Resource
Navigate to the Resources tab in your Retool instance and click Add Resource. Select REST API from the list of resource types. Name the resource 'SEMrush API'. In the Base URL field, enter https://api.semrush.com. All SEMrush API endpoints are accessed via this base URL with report-specific query parameters appended to each query. SEMrush authenticates API requests using an API key passed as a URL query parameter named key. Rather than adding it to each query individually, add it as a default URL parameter at the resource level. In the URL Parameters section, click Add Parameter and set the name to key and the value to your SEMrush API key. For better security, store the API key as a configuration variable. Go to Retool's Settings → Configuration Variables, create a variable named SEMRUSH_API_KEY, mark it as Secret, and paste your key. Then in the resource's URL parameter value field, use {{ retoolContext.configVars.SEMRUSH_API_KEY }} instead of the raw key. SEMrush's API responses use a pipe-delimited text format (not JSON) for most reporting endpoints. Each response includes a header row followed by data rows, all separated by semicolons or pipes depending on the endpoint. You will use JavaScript transformers to parse this format. Leave all other resource settings at their defaults and click Save Changes.
Pro tip: SEMrush API access is available on Pro, Guru, and Business plans. Check your monthly API unit balance in SEMrush's Account Settings → API section before building dashboards that make many calls. Guru and Business plans include significantly more API units than Pro.
Expected result: The SEMrush API resource is saved in Retool with the base URL and API key URL parameter configured. The resource is available for queries across all apps in your workspace.
Query domain analytics and organic metrics
Create your first SEMrush query to retrieve domain overview metrics. In your Retool app, open the Code panel and click + to add a query. Name it getDomainAnalytics and select the SEMrush API resource. Set Method to GET. In the Path field, leave it empty (SEMrush's reporting API uses the base URL with query parameters). Add the following URL parameters to build the report request: - type: domain_ranks (this report type returns organic and paid traffic metrics for a domain) - domain: {{ textInput_domain.value }} (the domain to analyze, e.g., example.com) - database: us (the SEMrush database — us for US data, uk for UK, etc.) - export_columns: Dn,Rk,Or,Ot,Oc,Ad,At,Ac (columns: Domain, Rank, Organic Keywords, Organic Traffic, Organic Cost, Adwords Keywords, Adwords Traffic, Adwords Cost) - display_limit: 1 SEMrush returns this data as pipe-delimited text. Add a JavaScript transformer to parse it: For the keyword list query, create a second query named getDomainKeywords: - type: domain_organic - domain: {{ textInput_domain.value }} - database: us - export_columns: Ph,Po,Pp,Pd,Nq,Cp,Co,Kd,Tr,Tc,In,Ur,Fk,Ts (Phrase, Position, Previous Position, Position Diff, Volume, CPC, Competition, KD, Traffic, Traffic Cost, Number of Results, URL, Featured Snippet, Timestamp) - display_limit: 100 - display_sort: tr_desc (sort by traffic descending) Bind getDomainKeywords to a Table component and add a text input filter for keyword phrase matching.
1// JavaScript transformer — parse SEMrush pipe-delimited response2// SEMrush returns: header_row\n data_row1\n data_row2\n ...3const responseText = data; // raw API response text45if (!responseText || typeof responseText !== 'string') {6 return [];7}89const lines = responseText.trim().split('\n').filter(l => l.trim());10if (lines.length < 2) return []; // No data rows1112const headers = lines[0].split(';');1314return lines.slice(1).map(line => {15 const values = line.split(';');16 const row = {};17 headers.forEach((header, i) => {18 row[header.trim()] = values[i] ? values[i].trim() : '';19 });20 return row;21}).filter(row => Object.values(row).some(v => v !== ''));Pro tip: SEMrush API responses for most reports use semicolons (;) as delimiters, not pipes, despite being called 'pipe-delimited' in some documentation. Always check the actual response format in Retool's query preview panel and adjust your transformer's split character accordingly.
Expected result: The getDomainAnalytics query returns a parsed object with the domain's organic keywords count, estimated traffic, and traffic value. The getDomainKeywords query populates a table with up to 100 top-ranking keywords with their positions and traffic estimates.
Fetch keyword rankings and position change data
Build detailed keyword ranking queries that show position changes over time. Create a query named getKeywordPositionHistory: - Path: leave empty (use URL parameters only) - URL parameters: - type: domain_organic - domain: {{ textInput_domain.value }} - database: us - export_columns: Ph,Po,Pp,Pd,Nq,Cp,Kd,Ur - display_filter: +|Po|Lt|11 (filter to page 1 rankings, position less than 11) - display_sort: nq_desc (sort by search volume) - display_limit: 50 The Pp (Previous Position) and Pd (Position Difference) columns in SEMrush's domain_organic report show week-over-week changes. Add a JavaScript transformer that calculates a change_direction field: 'improved' when Pd is negative (lower position number = better), 'declined' when Pd is positive, and 'stable' when 0. In your Retool Table component, add conditional column formatting to the position change column: green background for improved keywords, red for declined, gray for stable. For tracking specific keywords (not domain-wide), create a keyword_overview query: - type: phrase_this - phrase: {{ textInput_keyword.value }} - database: us - export_columns: Ph,Nq,Cp,Co,Nr,Td (Phrase, Volume, CPC, Competition, Results, Trend) Bind a Text Input component for keyword lookup. The phrase_this report type returns volume, CPC, competition score, and a 12-month search trend array for any specific keyword.
1// JavaScript transformer — add position change indicators to keyword data2const rows = parsedKeywords || []; // Use the parsed result from previous transformer34return rows.map(row => {5 const currentPos = parseInt(row.Po) || 0;6 const prevPos = parseInt(row.Pp) || 0;7 const posDiff = parseInt(row.Pd) || 0;8 const volume = parseInt(row.Nq) || 0;910 // Position change: negative diff means position number decreased = improved ranking11 const changeDirection = posDiff < 0 ? 'improved'12 : posDiff > 0 ? 'declined' : 'stable';1314 return {15 keyword: row.Ph || '',16 current_position: currentPos || 'N/A',17 previous_position: prevPos || 'N/A',18 position_change: posDiff !== 019 ? (posDiff < 0 ? `▲ ${Math.abs(posDiff)}` : `▼ ${posDiff}`)20 : '—',21 change_direction: changeDirection,22 search_volume: volume.toLocaleString(),23 cpc: row.Cp ? `$${parseFloat(row.Cp).toFixed(2)}` : 'N/A',24 keyword_difficulty: row.Kd ? `${row.Kd}%` : 'N/A',25 ranking_url: row.Ur || 'N/A'26 };27}).sort((a, b) => {28 const aVol = parseInt(a.search_volume.replace(/,/g, '')) || 0;29 const bVol = parseInt(b.search_volume.replace(/,/g, '')) || 0;30 return bVol - aVol;31});Pro tip: SEMrush's position change data is calculated weekly. Run your getDomainKeywords query on Mondays to get the freshest position change data, as SEMrush updates organic rankings data once per week for most databases.
Expected result: The keyword rankings table shows page-1 keywords with color-coded position change indicators. Improved keywords (moved up in rankings) appear with green upward arrows, declined keywords show red downward arrows.
Build backlink and referring domain queries
Create queries to retrieve backlink data from SEMrush's Backlinks API. Create a query named getBacklinkOverview: - URL parameters: - type: backlinks_overview - target: {{ textInput_domain.value }} - target_type: root_domain - export_columns: ascore,total,domains_num,urls_num,ips_num,follows_num,nofollows_num,texts_num,images_num This returns the domain's Authority Score (SEMrush's equivalent of Domain Rating), total backlinks, referring domain count, and follow/nofollow distribution. Display these as Stat components at the top of your backlink panel. Create a query named getTopReferringDomains: - type: backlinks_refdomains - target: {{ textInput_domain.value }} - target_type: root_domain - export_columns: domain_ascore,domain,domains_num,backlinks_num,last_seen,first_seen - display_sort: domain_ascore_desc (highest authority domains first) - display_limit: 50 Create a query named getNewAndLostBacklinks: - type: backlinks_tlt (this report shows new and lost backlinks over time) - target: {{ textInput_domain.value }} - target_type: root_domain - export_columns: date,new,lost Bind getNewAndLostBacklinks to a Chart component configured as a grouped bar chart with date on the x-axis and two series: new backlinks (blue bars) and lost backlinks (red bars). This visualization shows link acquisition momentum and helps identify when link losses occur (often corresponding to competitor activity or site changes).
1// JavaScript transformer — format referring domains for display2const rows = parsedBacklinkData || [];34return rows.map(row => ({5 domain: row.domain || 'N/A',6 authority_score: parseInt(row.domain_ascore) || 0,7 authority_label: parseInt(row.domain_ascore) >= 70 ? 'High'8 : parseInt(row.domain_ascore) >= 40 ? 'Medium' : 'Low',9 total_backlinks: parseInt(row.backlinks_num) || 0,10 first_seen: row.first_seen11 ? new Date(row.first_seen).toLocaleDateString()12 : 'N/A',13 last_seen: row.last_seen14 ? new Date(row.last_seen).toLocaleDateString()15 : 'N/A',16 is_new: row.first_seen17 ? new Date(row.first_seen) > new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)18 : false19})).sort((a, b) => b.authority_score - a.authority_score);Pro tip: SEMrush Backlinks API calls are more expensive in API units than Analytics API calls. For backlink dashboards that are checked frequently, consider running a Retool Workflow once per week to cache backlink data in Retool Database, then query the cached data in your live dashboard to preserve your API unit budget.
Expected result: The backlink overview panel shows Authority Score, total backlinks, and referring domain count as Stat components. The referring domains table lists top linking sites sorted by authority. The new/lost backlinks chart displays link acquisition trends over time.
Build competitor comparison and SEO summary panel
Create a competitor comparison panel that shows your domain's SEMrush metrics side by side with up to three competitors. This is the flagship view for weekly SEO reporting. Create a query named getCompetitorOverview that accepts a domain parameter and returns domain_ranks data. You'll trigger this query multiple times — once for your domain and once for each competitor — and merge the results in a JavaScript query. Create a JavaScript query named buildCompetitorTable: In your Retool app, add a TextInput for your domain and three additional TextInputs for competitor domains. Add a 'Run Comparison' button that triggers all four domain_ranks queries simultaneously using Retool's parallel query execution. After all four complete, the buildCompetitorTable JavaScript query merges the results into a single comparison dataset. Bind the result to a Table with columns for domain, organic keywords, estimated traffic, traffic value, paid keywords, and paid traffic. Add a Bar Chart showing organic traffic per domain. For the SEO reporting summary section, add Text components that generate a plain-English summary: 'Your domain ranks for {{ yourMetrics.organic_keywords }} organic keywords with estimated {{ yourMetrics.organic_traffic }} monthly visitors. Top competitor {{ competitorMetrics[0].domain }} ranks for {{ competitorMetrics[0].organic_keywords }} keywords.' This makes the dashboard useful for client reporting without requiring SEO expertise to interpret. For complex multi-domain SEO monitoring pipelines with automated weekly reporting, alert thresholds, and CRM integration, RapidDev's team can help build a comprehensive SEO operations center on Retool.
1// JavaScript query — build competitor comparison table from multiple domain queries2const domains = [3 { domain: textInput_domain.value, data: getDomainAnalytics.data },4 { domain: textInput_competitor1.value, data: getCompetitor1.data },5 { domain: textInput_competitor2.value, data: getCompetitor2.data },6 { domain: textInput_competitor3.value, data: getCompetitor3.data }7].filter(d => d.domain && d.data && d.data.length > 0);89return domains.map(({ domain, data }) => {10 const row = data[0] || {}; // First (and only) row from domain_ranks report11 return {12 domain: row.Domain || domain,13 organic_keywords: parseInt(row.Or || '0').toLocaleString(),14 organic_traffic: parseInt(row.Ot || '0').toLocaleString(),15 traffic_value: row.Oc ? `$${parseInt(row.Oc).toLocaleString()}` : 'N/A',16 paid_keywords: parseInt(row.Ad || '0').toLocaleString(),17 paid_traffic: parseInt(row.At || '0').toLocaleString(),18 semrush_rank: parseInt(row.Rk || '0').toLocaleString(),19 is_your_domain: domain === textInput_domain.value20 };21});Pro tip: When running multiple domain comparison queries simultaneously, use Retool's 'Run on manual trigger' setting for all competitor queries and trigger them together from the comparison button's onClick handler. This prevents the queries from running unnecessarily every time any input changes.
Expected result: The competitor comparison table shows all four domains side by side with their organic keyword counts, traffic estimates, and traffic values. The bar chart visually shows the traffic gap between your domain and competitors.
Common use cases
Build a domain analytics and organic traffic dashboard
Create a Retool dashboard that queries SEMrush's Domain Analytics API for your tracked domains, displaying organic keyword count, estimated organic traffic, traffic value, and top keywords sorted by search volume. Add a date range selector to compare metrics across different time periods and a Chart showing traffic trend over the past 12 months.
Build a domain analytics panel with a text input for domain name, a Stat row showing organic keywords count, estimated traffic, and traffic value from SEMrush, and a line chart displaying monthly organic traffic trends over the past year using the domain_ranks report type.
Copy this prompt to try it in Retool
Keyword position tracking and SERP monitoring panel
Build a Retool panel that fetches organic keyword rankings for your domain from SEMrush, showing each keyword's current position, previous position, search volume, keyword difficulty, and the ranking URL. Add filters for position ranges (top 3, positions 4-10, positions 11-20) and sort by traffic potential to help SEOs prioritize optimization efforts.
Create a keyword rankings dashboard that queries SEMrush for all organic keywords ranking on page 1, displays position, position change since last week, search volume, and CPC in a sortable Table, highlights keywords that moved up (green) or dropped (red) in position, and filters to show only keywords with search volume over 100.
Copy this prompt to try it in Retool
Competitor SEO comparison dashboard
Build a competitive intelligence panel that compares your domain's SEMrush metrics against up to four competitors side by side. Show organic keyword count, estimated traffic, domain authority (using backlink API), common keywords, and unique keywords for each domain. Add a Chart visualizing traffic trends for all domains over a selected time period.
Build a competitor comparison dashboard with text inputs for your domain and up to 3 competitor domains, a table comparing organic keyword count and estimated traffic for each domain, a bar chart showing traffic distribution, and a section listing the top keywords where competitors outrank you.
Copy this prompt to try it in Retool
Troubleshooting
API returns 'ERROR 50 :: NOTHING FOUND' for a domain query
Cause: SEMrush doesn't have data for the queried domain in the selected database, or the domain name format is incorrect (e.g., including https:// or trailing slash).
Solution: Enter only the bare domain name without protocol, subdomains (unless specifically needed), or trailing slashes (e.g., 'example.com' not 'https://www.example.com'). If the domain is new or low-traffic, SEMrush may have no data for it. Try switching the database parameter to a different country database if your target operates in a non-US market.
JavaScript transformer returns empty array despite seeing data in the raw response
Cause: SEMrush API responses use semicolons as delimiters for most reports, but some report types use different delimiters or return data in a slightly different format. The transformer's split character may not match.
Solution: In Retool's query preview panel, click 'Preview' and examine the raw response text. Check whether the delimiter between columns is a semicolon (;) or pipe (|). Update your transformer's split character to match: lines[0].split(';') or lines[0].split('|'). Also check if there's a trailing newline that creates an empty final element in the lines array.
1// Debug transformer — log raw response structure2console.log('Response type:', typeof data);3console.log('First 200 chars:', (data || '').substring(0, 200));4console.log('Lines count:', (data || '').split('\n').length);5return data; // Return raw for inspectionQueries return 'ERROR 120 :: REQUESTS LIMIT EXCEEDED'
Cause: Your SEMrush API plan's monthly unit limit has been reached, or you've exceeded the per-second request rate limit.
Solution: Check your API unit balance in SEMrush's Account Settings → API section. Each report type consumes a different number of units — domain_ranks costs 10 units per call, domain_organic costs 10 units per row returned. Reduce display_limit parameters to fetch fewer rows, cache results in Retool Database using Workflows, and avoid triggering multiple queries simultaneously on page load.
Backlinks overview query returns data but referring domains query is empty
Cause: The target_type parameter may be set incorrectly for the domain format. Using root_domain for a specific subdomain or URL produces no results.
Solution: Verify the target_type parameter matches your domain format: use 'root_domain' for the main domain (example.com), 'domain' for including all subdomains, or 'url' for a specific page URL. For most domain-level backlink analysis, use 'root_domain'. Also ensure the target parameter contains only the domain without protocol or path.
Best practices
- Store your SEMrush API key as a Secret configuration variable in Retool — never add it as a raw value in URL parameters that could be exposed in browser developer tools or logs.
- Monitor your API unit consumption in SEMrush's Account Settings → API section and set up alerts when you reach 80% of your monthly limit to avoid dashboard outages at month-end.
- Always parse SEMrush's pipe-delimited response with a reusable transformer function — create a standalone transformer named parseSemrushResponse that other queries can reference to avoid duplicating parsing logic.
- Use Retool Workflows on a weekly schedule to cache domain analytics and backlink data in Retool Database, then build your dashboard to read cached data — this preserves API units for on-demand queries.
- Filter organic keyword queries using display_filter to limit results to specific position ranges (e.g., page 1 only) and set display_limit to the minimum needed for your use case — each returned row costs API units.
- When building competitor comparison panels, add a manual 'Refresh' button rather than loading all competitor data on page load — this gives users control over when API units are consumed.
- Combine SEMrush domain analytics with Google Search Console data in the same Retool app to cross-reference SEMrush's traffic estimates against actual GSC impression data for your own domain.
Alternatives
Ahrefs is more focused on backlink analysis and has a highly accurate link index, while SEMrush provides broader digital marketing coverage including paid search, social, and content marketing analytics.
Moz is strong for Domain Authority tracking and local SEO, while SEMrush offers a more comprehensive all-in-one marketing platform with competitive intelligence and advertising data.
Google Search Console provides authoritative first-party search performance data for your own domain, while SEMrush provides competitive intelligence and keyword data for any domain including competitors.
Frequently asked questions
Does SEMrush have a native connector in Retool?
No, SEMrush does not have a native connector in Retool. You connect it via a REST API Resource using your SEMrush API key as a URL parameter. This means you need to know SEMrush's report type parameters and column codes to build queries, but all major reports — domain analytics, keyword research, backlinks, and site audits — are accessible through the API.
Which SEMrush plan do I need for API access?
API access is included in SEMrush's Pro, Guru, and Business plans. It is not available on the free plan. The Pro plan includes 3,000 API units per month, Guru includes 5,000 units, and Business includes 10,000 units. Some API reports consume units per row returned, so a query with display_limit=100 may cost 100+ units depending on the report type. Check SEMrush's API documentation for the unit cost of each report type.
How do I parse SEMrush's response format in Retool?
SEMrush's API returns data as semicolon-delimited text, not JSON. The first line is a header row with column names, followed by data rows. Use a JavaScript transformer in Retool to parse this: split the response by newline to get rows, split the first row by semicolon to get headers, then map remaining rows into objects using the headers as keys. This parsed array can then be bound to Retool Table and Chart components.
Can I access SEMrush site audit data through the API?
SEMrush's Site Audit results are accessible via the API, but the endpoint structure differs from the reporting API. Site Audit data is accessed through the /management/projects and /reports/site-audit endpoints, which require your project ID. First create or identify your site audit project in SEMrush, retrieve its project ID from the projects API, then use that ID to fetch audit scores, issue counts, and page-level audit results.
How can I track keyword position changes over time in Retool?
Use a Retool Workflow on a weekly schedule to query SEMrush for your domain's keyword rankings and store the results in Retool Database or PostgreSQL. Each week's query results are stored with a date stamp. Your dashboard then queries the historical data to calculate week-over-week position changes by comparing the current week's positions to the previous week's stored data, giving you full historical tracking without consuming API units on every dashboard load.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation