<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Emma Watson</title>
    <description>The latest articles on DEV Community by Emma Watson (@emma-watson3).</description>
    <link>https://dev.to/emma-watson3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3948788%2F68370d2a-f4a5-4563-a2b6-398c299f03bf.png</url>
      <title>DEV Community: Emma Watson</title>
      <link>https://dev.to/emma-watson3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emma-watson3"/>
    <language>en</language>
    <item>
      <title>Google PageRank Is Dead—Here’s How I’m Checking Domain Trust in 2026</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Fri, 21 Aug 2026 05:17:50 +0000</pubDate>
      <link>https://dev.to/emma-watson3/google-pagerank-is-dead-heres-how-im-checking-domain-trust-in-2026-52e</link>
      <guid>https://dev.to/emma-watson3/google-pagerank-is-dead-heres-how-im-checking-domain-trust-in-2026-52e</guid>
      <description>&lt;p&gt;Google killed the public PageRank API years ago, but you still see outdated metrics in every SEO audit. The problem is that legacy tools show you a number that no longer reflects how Google actually evaluates trust. You are essentially looking at a 2013 snapshot to make 2025 decisions.&lt;/p&gt;

&lt;p&gt;The real challenge is separating historical authority from current relevance. A domain can have a high PageRank history but be a spam-riddled shell today. Meanwhile, a fresh site with excellent content and strong backlinks gets ignored because it lacks that old metric.&lt;/p&gt;

&lt;p&gt;That is why we built the Google PageRank Checker with a dual-signal approach. You get the legacy PageRank data for historical context, but you also get the SERPSpur Trust Rate, which analyzes current domain trust based on live ranking signals, backlink quality, and content integrity. This gives you a complete picture in seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fso64rdki8bstvk6wtb62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fso64rdki8bstvk6wtb62.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of guessing whether a domain is worth pursuing for outreach or link building, you can compare both numbers side-by-side. If the legacy PageRank is high but the Trust Rate is low, you know the authority has decayed. If the Trust Rate is high, you have found a hidden gem that legacy tools would have missed.&lt;/p&gt;

&lt;p&gt;Stop relying on outdated data. Check the historical metric, but verify it against the current reality. Run your authority analysis with both signals and make decisions based on what is true today, not what was true a decade ago.&lt;a href="https://serpspur.com/tool/google-pagerank-checker/" rel="noopener noreferrer"&gt;https://serpspur.com/tool/google-pagerank-checker/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a Python Keyword Scoring System That Finds Low-Competition SEO Opportunities by Country</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Wed, 19 Aug 2026 04:40:21 +0000</pubDate>
      <link>https://dev.to/emma-watson3/i-built-a-python-keyword-scoring-system-that-finds-low-competition-seo-opportunities-by-country-3j60</link>
      <guid>https://dev.to/emma-watson3/i-built-a-python-keyword-scoring-system-that-finds-low-competition-seo-opportunities-by-country-3j60</guid>
      <description>&lt;p&gt;When I started building my first real SaaS product, I thought I had the SEO part figured out. I was wrong. My biggest bottleneck wasn't writing content—it was validating whether the keywords I was targeting actually had commercial intent in specific markets.&lt;/p&gt;

&lt;p&gt;Here is the thing: Search volume is a vanity metric if you don't understand the competition. A keyword might have 10,000 monthly searches in the US, but if the top 10 results are all authority domains with massive backlink profiles, you're wasting your time. Conversely, a keyword with 500 searches in Germany might have zero ads competition and a keyword difficulty score under 15, which is a goldmine for a new domain.&lt;/p&gt;

&lt;p&gt;I recently ran a workflow that completely changed how I prioritize my content calendar. Instead of guessing, I wrote a simple Python script to pull data from the SERPSpur Keyword Research Tool and score opportunities based on a custom formula.&lt;/p&gt;

&lt;p&gt;Here is the core logic I used to filter out the noise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_keywords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Fetch data from the API (pseudo-code)
&lt;/span&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_serpspur_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Custom scoring: (Search Volume * CPC * 0.5) / (KD + Ad Competition)
&lt;/span&gt;        &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cpc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;difficulty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ads_competition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c1"&gt;# Filter: Find low-competition, high-value keywords
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;difficulty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ads_competition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;keyword&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cpc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cpc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;kd&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;difficulty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Example usage for the German market
&lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seo tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keyword planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backlink checker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;analyze_keywords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight here is the &lt;strong&gt;country-specific data&lt;/strong&gt;. The tool allows you to switch to specific countries, which is crucial. What works in the US rarely works in France or Japan. The ads competition metric is particularly useful—if nobody is bidding on a keyword via Google Ads, it usually means the traffic is too cold for commercial conversion, or the market is underserved.&lt;/p&gt;

&lt;p&gt;My actual workflow now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Brainstorm 50–100 seed keywords.&lt;/li&gt;
&lt;li&gt;Pull volume, CPC, KD, and Ads Competition for target countries.&lt;/li&gt;
&lt;li&gt;Filter by KD &amp;lt; 25 and Ads Competition &amp;lt; 0.3.&lt;/li&gt;
&lt;li&gt;Rank by a weighted score that prioritizes CPC (revenue potential) over raw volume.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach helped me find a niche in the Dutch market where the difficulty was 12 and CPC was $3.50. I published two articles targeting those terms, and within three weeks, I was ranking on page one.&lt;/p&gt;

&lt;p&gt;The point isn't to promote a specific tool—it's to stop treating keyword research as a one-size-fits-all metric. Use the filters available to you. Look at the ads competition. Look at the difficulty score relative to your domain authority. And always, always segment by country. Your organic traffic strategy will thank you.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Built a Node.js Workflow for Bulk Backlink Exports</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Mon, 17 Aug 2026 04:36:37 +0000</pubDate>
      <link>https://dev.to/emma-watson3/how-i-built-a-nodejs-workflow-for-bulk-backlink-exports-g7i</link>
      <guid>https://dev.to/emma-watson3/how-i-built-a-nodejs-workflow-for-bulk-backlink-exports-g7i</guid>
      <description>&lt;p&gt;If you’ve ever tried pulling backlink data for dozens of competitor domains, you’ve probably run into the same problems: API rate limits, expensive credits, inconsistent data, and spreadsheets full of manually copied results.&lt;/p&gt;

&lt;p&gt;I recently ran into this while working on a large SEO audit. I needed backlink data for more than 50 domains, and manually collecting everything from multiple tools was taking far too long.&lt;/p&gt;

&lt;p&gt;Instead of continuing with the spreadsheet approach, I built a small Node.js workflow to handle the process automatically.&lt;/p&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;Input: A list of domains&lt;br&gt;
Output: A clean, normalized CSV containing the backlink data&lt;/p&gt;

&lt;p&gt;The interesting part wasn't actually fetching the data. The real challenge was managing concurrency, throttling, retries, and failed requests.&lt;/p&gt;

&lt;p&gt;Why Rate Limiting Matters&lt;/p&gt;

&lt;p&gt;Most backlink APIs have request limits. If you send dozens of requests simultaneously, you'll eventually start receiving HTTP 429 Too Many Requests responses.&lt;/p&gt;

&lt;p&gt;For example, sending 50 requests at once might look efficient, but it's usually a bad idea.&lt;/p&gt;

&lt;p&gt;A better approach is to maintain a controlled queue and process a limited number of requests concurrently.&lt;/p&gt;

&lt;p&gt;Here's the basic pattern I used:&lt;/p&gt;

&lt;p&gt;const pLimit = require("p-limit");&lt;/p&gt;

&lt;p&gt;const delay = (ms) =&amp;gt;&lt;br&gt;
  new Promise((resolve) =&amp;gt; setTimeout(resolve, ms));&lt;/p&gt;

&lt;p&gt;async function exportBacklinks(domains) {&lt;br&gt;
  const limit = pLimit(5);&lt;br&gt;
  const results = [];&lt;/p&gt;

&lt;p&gt;const tasks = domains.map((domain, index) =&amp;gt;&lt;br&gt;
    limit(async () =&amp;gt; {&lt;br&gt;
      // Simulate an API request&lt;br&gt;
      await delay(1000 + Math.random() * 500);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // Replace this with your actual API request
  const data = `Data for ${domain}`;


  results.push({
    domain,
    data
  });


  console.log(
    `Processed ${index + 1}/${domains.length}: ${domain}`
  );
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;);&lt;/p&gt;

&lt;p&gt;await Promise.all(tasks);&lt;/p&gt;

&lt;p&gt;return results;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The important part here is:&lt;/p&gt;

&lt;p&gt;const limit = pLimit(5);&lt;/p&gt;

&lt;p&gt;Instead of firing every request simultaneously, the queue allows only five operations to run at the same time.&lt;/p&gt;

&lt;p&gt;That makes the workflow much less likely to overwhelm an API.&lt;/p&gt;

&lt;p&gt;Don't Forget Retries&lt;/p&gt;

&lt;p&gt;Concurrency control alone isn't enough.&lt;/p&gt;

&lt;p&gt;APIs can still return temporary errors, especially when you're processing hundreds or thousands of URLs.&lt;/p&gt;

&lt;p&gt;For 429 responses, an exponential backoff strategy is useful. Instead of retrying immediately, increase the delay after each failed attempt.&lt;/p&gt;

&lt;p&gt;A simple strategy looks like this:&lt;/p&gt;

&lt;p&gt;Attempt 1 → wait 1 second&lt;br&gt;
Attempt 2 → wait 2 seconds&lt;br&gt;
Attempt 3 → wait 4 seconds&lt;br&gt;
Attempt 4 → wait 8 seconds&lt;/p&gt;

&lt;p&gt;You should also set a maximum number of retries so a permanently failing domain doesn't keep your entire queue running indefinitely.&lt;/p&gt;

&lt;p&gt;Normalize the Data Before Exporting&lt;/p&gt;

&lt;p&gt;Another issue I discovered was inconsistent URL formatting.&lt;/p&gt;

&lt;p&gt;You might receive:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://example.com/page" rel="noopener noreferrer"&gt;https://example.com/page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://example.com/page/" rel="noopener noreferrer"&gt;https://example.com/page/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on your analysis, these could end up being treated as different URLs.&lt;/p&gt;

&lt;p&gt;Before deduplicating or comparing data, normalize the URLs.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;function normalizeUrl(url) {&lt;br&gt;
  return url&lt;br&gt;
    .trim()&lt;br&gt;
    .replace(/\/$/, "");&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;For production workflows, I'd recommend using a proper URL parser rather than relying only on string manipulation.&lt;/p&gt;

&lt;p&gt;Exporting to CSV&lt;/p&gt;

&lt;p&gt;Once the backlink data has been collected and normalized, exporting it is relatively straightforward.&lt;/p&gt;

&lt;p&gt;Libraries such as json2csv can convert JavaScript objects into CSV format that you can open in Excel, Google Sheets, or process with Python.&lt;/p&gt;

&lt;p&gt;The resulting dataset might look something like:&lt;/p&gt;

&lt;p&gt;domain,url,anchor,type&lt;br&gt;
example.com,&lt;a href="https://example.com/page,SEO" rel="noopener noreferrer"&gt;https://example.com/page,SEO&lt;/a&gt; guide,dofollow&lt;br&gt;
another.com,&lt;a href="https://another.com/resource,marketing,referral" rel="noopener noreferrer"&gt;https://another.com/resource,marketing,referral&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having everything in a consistent format makes the next stage—actual SEO analysis—much easier.&lt;/p&gt;

&lt;p&gt;The Real Problem With Bulk Backlink Analysis&lt;/p&gt;

&lt;p&gt;The script itself wasn't the biggest challenge.&lt;/p&gt;

&lt;p&gt;The bigger issue was API cost and infrastructure.&lt;/p&gt;

&lt;p&gt;When you're analyzing a large number of domains, every API request can consume credits. If you're doing this regularly for multiple clients, those costs can add up quickly.&lt;/p&gt;

&lt;p&gt;That's why I eventually moved this particular workflow to a dedicated tool: SERPSpur's Bulk Backlink Exporter.&lt;/p&gt;

&lt;p&gt;Bulk Backlink Exporter&lt;/p&gt;

&lt;p&gt;Instead of writing and maintaining the entire queue, throttling, and export pipeline myself, I can provide the domains and get structured backlink data ready for analysis.&lt;/p&gt;

&lt;p&gt;For one-off experiments, writing your own script is useful. For repetitive SEO audits, using an existing workflow can save a considerable amount of development time.&lt;/p&gt;

&lt;p&gt;Lessons From the Workflow&lt;/p&gt;

&lt;p&gt;If you're building your own bulk backlink exporter, I'd keep these principles in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Respect API limits&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't assume that because you can technically send 100 requests at once, you should.&lt;/p&gt;

&lt;p&gt;Use concurrency limits and follow the API provider's documented rate limits.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implement exponential backoff&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Temporary failures happen. Give the server time before retrying instead of immediately sending another request.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Normalize your data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Standardize URLs, domains, anchors, and link types before running comparisons or deduplication.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log failures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When processing 50+ domains, you need to know exactly which request failed and why.&lt;/p&gt;

&lt;p&gt;A useful log should include:&lt;/p&gt;

&lt;p&gt;Domain&lt;br&gt;
Request status&lt;br&gt;
Error message&lt;br&gt;
Retry count&lt;br&gt;
Timestamp&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Separate collection from analysis&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't try to perform all your SEO analysis while collecting the data.&lt;/p&gt;

&lt;p&gt;First create a clean dataset. Then analyze metrics such as referring domains, anchor text, link types, authority, and link growth.&lt;/p&gt;

&lt;p&gt;Build It Yourself or Use a Tool?&lt;/p&gt;

&lt;p&gt;Building your own exporter is a great learning project if you want to understand asynchronous JavaScript, API limits, queues, and data processing.&lt;/p&gt;

&lt;p&gt;But if your main goal is SEO analysis rather than building infrastructure, there's little value in spending an entire weekend maintaining the plumbing.&lt;/p&gt;

&lt;p&gt;The most useful part of backlink analysis happens after the data is collected: identifying valuable referring domains, finding competitor gaps, analyzing anchor patterns, and turning those findings into an actionable link-building strategy.&lt;/p&gt;

&lt;p&gt;Automate the repetitive part so you can spend more time analyzing the data.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Find Backlink Gaps Without Spending Hours in Spreadsheets</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Sat, 15 Aug 2026 04:37:41 +0000</pubDate>
      <link>https://dev.to/emma-watson3/how-to-find-backlink-gaps-without-spending-hours-in-spreadsheets-1nfo</link>
      <guid>https://dev.to/emma-watson3/how-to-find-backlink-gaps-without-spending-hours-in-spreadsheets-1nfo</guid>
      <description>&lt;p&gt;Backlinks are still an important part of SEO, but simply being told to “build more links” doesn’t give you a useful strategy. The real question is: which websites should you target?&lt;/p&gt;

&lt;p&gt;That’s where backlink gap analysis becomes useful.&lt;/p&gt;

&lt;p&gt;The basic idea is straightforward: compare your backlink profile with your competitors and identify domains that link to them but don’t link to you. These domains can be valuable prospects because they’ve already shown that they’re willing to reference websites in your niche.&lt;/p&gt;

&lt;p&gt;The Manual Approach&lt;/p&gt;

&lt;p&gt;You can do this manually by exporting backlink data from an SEO tool, importing the files into a spreadsheet, and using formulas such as VLOOKUP or INDEX-MATCH to identify domains that appear in your competitors’ profiles but not yours.&lt;/p&gt;

&lt;p&gt;It works, but it gets tedious quickly.&lt;/p&gt;

&lt;p&gt;If you already have your backlink data in CSV files, you can automate the basic comparison with Python:&lt;/p&gt;

&lt;p&gt;import pandas as pd&lt;/p&gt;

&lt;p&gt;def find_gaps(your_file, competitor_file):&lt;br&gt;
    you = pd.read_csv(your_file, usecols=["Domain"])&lt;br&gt;
    competitor = pd.read_csv(competitor_file, usecols=["Domain"])&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;your_domains = set(you["Domain"].str.lower().dropna())
competitor_domains = set(competitor["Domain"].str.lower().dropna())


gaps = competitor_domains - your_domains
return sorted(gaps)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;opportunities = find_gaps(&lt;br&gt;
    "my_links.csv",&lt;br&gt;
    "competitor_links.csv"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;print(f"Found {len(opportunities)} opportunities")&lt;/p&gt;

&lt;p&gt;for domain in opportunities[:20]:&lt;br&gt;
    print(domain)&lt;/p&gt;

&lt;p&gt;This gives you a clean list of domains that appear in the competitor's backlink profile but not yours.&lt;/p&gt;

&lt;p&gt;The code isn't really the difficult part, though. The quality of your backlink data matters much more.&lt;/p&gt;

&lt;p&gt;A Faster Way to Find the Gaps&lt;/p&gt;

&lt;p&gt;If you don't want to spend time exporting CSVs and comparing spreadsheets, I've been using the &lt;strong&gt;&lt;a href="https://serpspur.com/tool/backlink-gap/" rel="noopener noreferrer"&gt;https://serpspur.com/tool/backlink-gap/&lt;/a&gt;&lt;/strong&gt; from SERPSpur for this type of workflow.&lt;/p&gt;

&lt;p&gt;You enter your domain and competitor domains, and the tool compares their referring domains to identify websites you're missing.&lt;/p&gt;

&lt;p&gt;One useful part is being able to prioritize opportunities instead of treating every backlink equally. A relevant, authoritative publication is usually a much better prospect than a random low-quality directory.&lt;/p&gt;

&lt;p&gt;For example, during a recent analysis, I found a niche technology publication that was already linking to several competitors but had no link to my site. That immediately gave me a potential outreach target.&lt;/p&gt;

&lt;p&gt;How I Use Backlink Gap Analysis&lt;/p&gt;

&lt;p&gt;My workflow is fairly simple:&lt;/p&gt;

&lt;p&gt;Run a backlink gap analysis against several competitors.&lt;br&gt;
Export or record the most relevant missing domains.&lt;br&gt;
Prioritize sites based on relevance and authority.&lt;br&gt;
Research the pages where competitors earned their links.&lt;br&gt;
Create a personalized outreach pitch.&lt;br&gt;
Track the prospects and follow up.&lt;/p&gt;

&lt;p&gt;I usually focus on the top 20–30 realistic opportunities rather than trying to contact hundreds of domains at once.&lt;/p&gt;

&lt;p&gt;And the outreach matters.&lt;/p&gt;

&lt;p&gt;Don't send a generic message saying:&lt;/p&gt;

&lt;p&gt;“Can you please link to my website?”&lt;/p&gt;

&lt;p&gt;Instead, explain why your content would actually be useful to their audience. If you have a newer statistic, original research, case study, or better resource, mention that specifically.&lt;/p&gt;

&lt;p&gt;Backlink Gaps Are More Useful Than Random Link Building&lt;/p&gt;

&lt;p&gt;The biggest advantage of competitor backlink analysis is that you're not starting from zero.&lt;/p&gt;

&lt;p&gt;You're looking at websites that have already demonstrated some willingness to link to businesses or content in your space.&lt;/p&gt;

&lt;p&gt;That doesn't guarantee they'll link to you, but it gives you a much more qualified prospect list than blindly searching for websites.&lt;/p&gt;

&lt;p&gt;If you're already using tools such as Ahrefs or Semrush, you can perform this analysis there as well. For smaller projects, though, a lightweight backlink gap workflow can be enough to uncover some surprisingly good opportunities.&lt;/p&gt;

&lt;p&gt;The goal isn't to build the most backlinks. It's to find the right websites and give them a genuine reason to mention your content.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Turned a 50+ Domain Backlink Audit Into a 30-Minute Workflow</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Sat, 08 Aug 2026 05:36:34 +0000</pubDate>
      <link>https://dev.to/emma-watson3/how-i-turned-a-50-domain-backlink-audit-into-a-30-minute-workflow-278k</link>
      <guid>https://dev.to/emma-watson3/how-i-turned-a-50-domain-backlink-audit-into-a-30-minute-workflow-278k</guid>
      <description>&lt;p&gt;Backlink analysis is one of those tasks that seems simple until you need to do it at scale. I recently needed to export backlink data for 50+ domains to identify link-building opportunities for a client, and manually copying data from various tools was painfully slow.&lt;/p&gt;

&lt;p&gt;That's when I discovered the &lt;a href="https://serpspur.com/tool/bulk-backlink-exporter/" rel="noopener noreferrer"&gt;Bulk Backlink Exporter&lt;/a&gt; from SERPSpur. It lets you pull comprehensive backlink data in one go, which is perfect for competitive analysis or portfolio-wide audits.&lt;/p&gt;

&lt;p&gt;The key feature is the ability to organize data by domain, anchor text, and link type—all exportable to CSV for further processing. Here's how I structured my analysis pipeline:&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
import pandas as pd&lt;/p&gt;

&lt;p&gt;df = pd.read_csv('backlinks_export.csv')&lt;/p&gt;

&lt;h1&gt;
  
  
  Filter for high-value links
&lt;/h1&gt;

&lt;p&gt;df['domain_authority'] = df['domain_authority'].astype(int)&lt;br&gt;
high_value = df[df['domain_authority'] &amp;gt; 50]&lt;/p&gt;

&lt;h1&gt;
  
  
  Group by target domain
&lt;/h1&gt;

&lt;p&gt;summary = high_value.groupby('target_domain').agg(&lt;br&gt;
    total_links=('url', 'count'),&lt;br&gt;
    avg_authority=('domain_authority', 'mean')&lt;br&gt;
).reset_index()&lt;/p&gt;

&lt;p&gt;print(summary.head(10))&lt;/p&gt;

&lt;p&gt;This approach let me quickly identify which competitor domains had the strongest link profiles and where the gaps were in our own strategy.&lt;/p&gt;

&lt;p&gt;One tip: when exporting large datasets, always filter by date range first. The tool supports this, and it saves you from processing irrelevant historical data that could skew your analysis.&lt;/p&gt;

&lt;p&gt;I also found it useful for spotting toxic backlinks across multiple domains at once. By exporting everything and running a simple script to flag suspicious anchors, I could prioritize disavow actions without manually scanning each domain.&lt;/p&gt;

&lt;p&gt;For anyone managing multiple sites or doing agency work, this kind of bulk export is a game-changer. It turns a weekend project into a 30-minute task.&lt;/p&gt;

&lt;p&gt;How do you handle large-scale backlink audits? I'm always looking for ways to streamline the process further.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Bulk Backlink Exports with Python: Stop Clicking "Next" and Automate Your SEO Workflow</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Wed, 05 Aug 2026 05:33:29 +0000</pubDate>
      <link>https://dev.to/emma-watson3/bulk-backlink-exports-with-python-stop-clicking-next-and-automate-your-seo-workflow-3mje</link>
      <guid>https://dev.to/emma-watson3/bulk-backlink-exports-with-python-stop-clicking-next-and-automate-your-seo-workflow-3mje</guid>
      <description>&lt;p&gt;If you've ever managed backlink audits for multiple websites, you've probably experienced the same frustration.&lt;/p&gt;

&lt;p&gt;Most SEO dashboards let you export a few hundred backlinks at a time. That's fine for a quick overview, but it's nowhere near enough for serious analysis. Large websites can have tens of thousands of backlinks, and manually exporting page after page quickly becomes a tedious process.&lt;/p&gt;

&lt;p&gt;A while ago, I got tired of downloading dozens of CSV files, merging them together, and cleaning everything in Excel before I could even begin my analysis.&lt;/p&gt;

&lt;p&gt;So I automated the entire workflow with Python.&lt;/p&gt;

&lt;p&gt;The Problem with Manual Exports&lt;/p&gt;

&lt;p&gt;Most backlink tools are designed around their web interface.&lt;/p&gt;

&lt;p&gt;That usually means:&lt;/p&gt;

&lt;p&gt;Exporting limited rows per download&lt;br&gt;
Clicking through multiple pages&lt;br&gt;
Combining several CSV files&lt;br&gt;
Cleaning inconsistent data formats&lt;br&gt;
Repeating the process for every client&lt;/p&gt;

&lt;p&gt;When you're handling multiple projects, this can easily consume hours every week.&lt;/p&gt;

&lt;p&gt;Instead of working with backlink data, you're spending your time collecting it.&lt;/p&gt;

&lt;p&gt;Automating the Process&lt;/p&gt;

&lt;p&gt;The solution was surprisingly straightforward.&lt;/p&gt;

&lt;p&gt;Rather than interacting with the dashboard, I queried structured backlink data programmatically and wrote everything directly into a single CSV file.&lt;/p&gt;

&lt;p&gt;The exact provider isn't important—the workflow works with any SEO platform that exposes backlink data through an API.&lt;/p&gt;

&lt;p&gt;Here's a simplified example.&lt;/p&gt;

&lt;p&gt;import requests&lt;br&gt;
import csv&lt;/p&gt;

&lt;p&gt;API_KEY = "your_key_here"&lt;/p&gt;

&lt;p&gt;DOMAINS = [&lt;br&gt;
    "example.com",&lt;br&gt;
    "client2.org",&lt;br&gt;
    "client3.net"&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;url = "&lt;a href="https://serpspur.com/api/v1/bulk-backlinks" rel="noopener noreferrer"&gt;https://serpspur.com/api/v1/bulk-backlinks&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;with open("backlinks.csv", "w", newline="", encoding="utf-8") as file:&lt;br&gt;
    writer = csv.writer(file)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;writer.writerow([
    "Domain",
    "Source URL",
    "Anchor Text",
    "Authority",
    "Status"
])

for domain in DOMAINS:

    params = {
        "api_key": API_KEY,
        "domain": domain,
        "limit": 5000
    }

    response = requests.get(url, params=params).json()

    for backlink in response["data"]:

        writer.writerow([
            domain,
            backlink["source"],
            backlink["anchor"],
            backlink["authority"],
            backlink["status"]
        ])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Instead of downloading dozens of files manually, the script exports everything into one clean dataset.&lt;/p&gt;

&lt;p&gt;Why This Saves So Much Time&lt;/p&gt;

&lt;p&gt;Once the backlinks are in CSV format, the real work begins.&lt;/p&gt;

&lt;p&gt;I can instantly:&lt;/p&gt;

&lt;p&gt;Filter only dofollow links&lt;br&gt;
Sort by authority score&lt;br&gt;
Find duplicate backlinks&lt;br&gt;
Analyze anchor text distribution&lt;br&gt;
Detect suspicious link patterns&lt;br&gt;
Build outreach prospect lists&lt;/p&gt;

&lt;p&gt;Because every project follows the same structure, the data is much easier to process with Python.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;import pandas as pd&lt;/p&gt;

&lt;p&gt;df = pd.read_csv("backlinks.csv")&lt;/p&gt;

&lt;p&gt;quality_links = df[&lt;br&gt;
    (df["Authority"] &amp;gt; 40) &amp;amp;&lt;br&gt;
    (df["Status"] == "dofollow")&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;print(quality_links.head())&lt;/p&gt;

&lt;p&gt;With just a few lines of code, you can create a high-quality outreach list instead of scrolling through thousands of rows manually.&lt;/p&gt;

&lt;p&gt;Don't Forget Pagination&lt;/p&gt;

&lt;p&gt;The sample above assumes everything fits into one response.&lt;/p&gt;

&lt;p&gt;In production, many APIs paginate large datasets.&lt;/p&gt;

&lt;p&gt;A more scalable solution loops through each page until no additional results are returned.&lt;/p&gt;

&lt;p&gt;Something like:&lt;/p&gt;

&lt;p&gt;page = 1&lt;/p&gt;

&lt;p&gt;while True:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;params = {
    "domain": domain,
    "page": page
}

response = requests.get(url, params=params).json()

if not response["data"]:
    break

# Process backlinks...

page += 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Pagination makes your exporter work equally well for websites with a few hundred backlinks or hundreds of thousands.&lt;/p&gt;

&lt;p&gt;Taking It Further&lt;/p&gt;

&lt;p&gt;Once you've collected backlink data, you can automate even more tasks:&lt;/p&gt;

&lt;p&gt;Generate toxicity reports&lt;br&gt;
Detect lost backlinks&lt;br&gt;
Compare competitors&lt;br&gt;
Monitor link growth over time&lt;br&gt;
Build outreach opportunities&lt;br&gt;
Create monthly SEO reports automatically&lt;/p&gt;

&lt;p&gt;At that point, Python becomes far more valuable than another spreadsheet.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;SEO isn't just about collecting data—it's about making that data useful.&lt;/p&gt;

&lt;p&gt;Automating repetitive tasks gives you more time to focus on strategy instead of clicking export buttons all afternoon.&lt;/p&gt;

&lt;p&gt;I built this workflow around SERPSpur's Bulk Backlink Exporter, but the overall approach works with any platform that provides structured backlink data through an API.&lt;/p&gt;

&lt;p&gt;If you're still downloading backlink reports one page at a time, it's probably time to automate the process. Your future self—and your clients—will appreciate it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Keyword Research Tool: Find High-Traffic, Low-Competition Keywords</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:03:23 +0000</pubDate>
      <link>https://dev.to/emma-watson3/keyword-research-tool-find-high-traffic-low-competition-keywords-4agg</link>
      <guid>https://dev.to/emma-watson3/keyword-research-tool-find-high-traffic-low-competition-keywords-4agg</guid>
      <description>&lt;p&gt;Keyword research is one of those tasks that seems simple until you actually try to do it properly. I've been refining my workflow recently, and the biggest game-changer was looking beyond just search volume. You really need to consider keyword difficulty, CPC, and ads competition to get a full picture. I built a small script that pulls data from multiple sources and aggregates it into a single CSV. The logic is straightforward: I query for a seed keyword, then expand it with long-tail variations, and finally score each one based on difficulty and potential ROI. The tricky part is filtering by country—search intent varies so much across markets. I found that grouping keywords by country and comparing the metrics side-by-side reveals opportunities you'd miss otherwise. If you want to skip the coding, SERPSpur's Keyword Research Tool does all of this in a few clicks. It gives you search volume, CPC, keyword difficulty, and ads competition for any country. Have you found any particular metric to be more reliable than others when evaluating keywords?&lt;a href="https://serpspur.com/tool/keyword-research-tool/" rel="noopener noreferrer"&gt;https://serpspur.com/tool/keyword-research-tool/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Stop Guessing Domain Quality—Check Trust Signals Before You Build Links</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Sat, 01 Aug 2026 09:24:06 +0000</pubDate>
      <link>https://dev.to/emma-watson3/stop-guessing-domain-quality-check-trust-signals-before-you-build-links-10bd</link>
      <guid>https://dev.to/emma-watson3/stop-guessing-domain-quality-check-trust-signals-before-you-build-links-10bd</guid>
      <description>&lt;p&gt;When I'm evaluating a domain for a project, I don't just look at backlinks. I want to know if the site is actually trustworthy from a technical standpoint. That means checking security headers, SSL configuration, and other behind-the-scenes signals that Google might use. Recently, I started using a dedicated trust rate checker to automate this process.&lt;/p&gt;

&lt;p&gt;The SerpSpur Trust Rate Checker does a deep dive into a domain's technical reputation. It analyzes things like HSTS, content security policy, and domain age to give you a single score. This is incredibly useful when you're vetting a potential link partner or buying an expired domain. You can instantly see if the site has been neglected or if it's been maintained with security best practices.&lt;/p&gt;

&lt;p&gt;Here's a quick script I use to batch-check multiple domains:&lt;/p&gt;

&lt;p&gt;bash&lt;/p&gt;

&lt;h1&gt;
  
  
  !/bin/bash
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Loop through a list of domains and check trust rates
&lt;/h1&gt;

&lt;p&gt;for domain in $(cat domains.txt); do&lt;br&gt;
  echo "Checking $domain..."&lt;br&gt;
  curl -s "&lt;a href="https://api.serpspur.com/trust-rate?domain=$domain" rel="noopener noreferrer"&gt;https://api.serpspur.com/trust-rate?domain=$domain&lt;/a&gt;" | jq '.score'&lt;br&gt;
done&lt;/p&gt;

&lt;p&gt;This saves me from manually visiting each site and inspecting the headers. It's a huge time-saver for outreach campaigns. If you're building a list of high-quality prospects, it's worth running them through this tool first. You can avoid wasting time on domains that have poor technical health. Try it yourself: &lt;a href="https://serpspur.com/tool/serpspur-trust-rate-checker/" rel="noopener noreferrer"&gt;https://serpspur.com/tool/serpspur-trust-rate-checker/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Find Available Domain Names Faster with an Instant Domain Suggestion Checker 🌐</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Mon, 27 Jul 2026 10:01:32 +0000</pubDate>
      <link>https://dev.to/emma-watson3/find-available-domain-names-faster-with-an-instant-domain-suggestion-checker-29e9</link>
      <guid>https://dev.to/emma-watson3/find-available-domain-names-faster-with-an-instant-domain-suggestion-checker-29e9</guid>
      <description>&lt;p&gt;I'm always looking for domain names for new projects, and checking availability one by one on registrars is tedious. I found a Domain Suggestion Checker that lets you check availability instantly and even suggests alternatives. It's great for brainstorming – you type in a keyword, and it shows what's available. For automation, I wrote a small script to batch check names from a list:&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
import requests&lt;/p&gt;

&lt;p&gt;def check_domain(domain):&lt;br&gt;
    url = f'&lt;a href="https://serpspur.com/tool/domain-sugesstion-checker/?domain=%7Bdomain%7D" rel="noopener noreferrer"&gt;https://serpspur.com/tool/domain-sugesstion-checker/?domain={domain}&lt;/a&gt;'&lt;br&gt;
    resp = requests.get(url)&lt;br&gt;
    if 'available' in resp.text.lower():&lt;br&gt;
        return f'{domain} is available'&lt;br&gt;
    return f'{domain} is taken'&lt;/p&gt;

&lt;p&gt;domains = ['mycoolidea.com', 'mycoolidea.net', 'mycoolidea.io']&lt;br&gt;
for d in domains:&lt;br&gt;
    print(check_domain(d))&lt;/p&gt;

&lt;p&gt;It's not perfect for bulk, but for quick checks it's handy. If you're domain hunting, give it a try. &lt;a href="https://serpspur.com" rel="noopener noreferrer"&gt;https://serpspur.com&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Take Control of AI Crawlers with an LLM.txt Generator for Smarter Content Access</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Wed, 22 Jul 2026 06:04:32 +0000</pubDate>
      <link>https://dev.to/emma-watson3/take-control-of-ai-crawlers-with-an-llmtxt-generator-for-smarter-content-access-2j04</link>
      <guid>https://dev.to/emma-watson3/take-control-of-ai-crawlers-with-an-llmtxt-generator-for-smarter-content-access-2j04</guid>
      <description>&lt;p&gt;If you’ve been building websites in the last year, you’ve likely noticed a new kind of visitor showing up in your logs—AI crawlers. Bots from OpenAI, Anthropic, Google, and others are scraping content to train models and feed knowledge bases. But unlike traditional search crawlers, these bots don’t always respect &lt;code&gt;robots.txt&lt;/code&gt; the same way. And even when they do, &lt;code&gt;robots.txt&lt;/code&gt; lacks the granularity to tell an AI &lt;em&gt;how&lt;/em&gt; to use your content.&lt;/p&gt;

&lt;p&gt;This is where &lt;code&gt;LLM.txt&lt;/code&gt; comes in. Think of it as a more modern, semantic companion to &lt;code&gt;robots.txt&lt;/code&gt;. While &lt;code&gt;robots.txt&lt;/code&gt; tells crawlers &lt;em&gt;what&lt;/em&gt; to avoid, &lt;code&gt;LLM.txt&lt;/code&gt; tells them &lt;em&gt;how&lt;/em&gt; to interact—what content is safe to summarize, what should be cited, and what’s strictly off-limits for training.&lt;/p&gt;

&lt;p&gt;I recently needed to set this up for a client project. Manually crafting the file is tedious, especially if you have a large site with multiple content types. That’s when I came across the SERPSpur LLM.txt Generator tool. It’s a straightforward web utility that lets you define rules for different AI crawlers and content sections. You can specify access levels—like “summarize only,” “allow training,” or “block entirely”—and it generates the full &lt;code&gt;LLM.txt&lt;/code&gt; file for you.&lt;/p&gt;

&lt;p&gt;Here’s a quick example of what the output looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# LLM.txt configuration for example.com
# Generated with SERPSpur LLM.txt Generator
&lt;/span&gt;
&lt;span class="n"&gt;User&lt;/span&gt;-&lt;span class="n"&gt;agent&lt;/span&gt;: *
&lt;span class="n"&gt;Allow&lt;/span&gt;: /&lt;span class="n"&gt;blog&lt;/span&gt;/
&lt;span class="n"&gt;Disallow&lt;/span&gt;: /&lt;span class="n"&gt;private&lt;/span&gt;/

&lt;span class="n"&gt;For&lt;/span&gt;-&lt;span class="n"&gt;model&lt;/span&gt;: &lt;span class="n"&gt;GPT&lt;/span&gt;-&lt;span class="m"&gt;4&lt;/span&gt;
  &lt;span class="n"&gt;Allow&lt;/span&gt;: /&lt;span class="n"&gt;docs&lt;/span&gt;/
  &lt;span class="n"&gt;Disallow&lt;/span&gt;: /&lt;span class="n"&gt;support&lt;/span&gt;/

&lt;span class="n"&gt;For&lt;/span&gt;-&lt;span class="n"&gt;model&lt;/span&gt;: &lt;span class="n"&gt;Claude&lt;/span&gt;
  &lt;span class="n"&gt;Allow&lt;/span&gt;: /&lt;span class="n"&gt;public&lt;/span&gt;/
  &lt;span class="n"&gt;Disallow&lt;/span&gt;: /&lt;span class="n"&gt;api&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax is still evolving, but the idea is clear: you can give different AI crawlers different permissions. This is huge for content creators who want to remain visible in AI-powered search but don’t want their proprietary tutorials or product docs used for model training.&lt;/p&gt;

&lt;p&gt;What I like most is that the generator also includes a preview of what your file will look like and checks for common errors. No more guessing if your syntax is correct. Once you’re happy, you just drop the &lt;code&gt;LLM.txt&lt;/code&gt; file into your site’s root directory.&lt;/p&gt;

&lt;p&gt;If you haven’t looked into LLM.txt yet, it’s worth the 10 minutes. As AI crawlers become the default way users discover content, having control over how your site is consumed isn’t just nice—it’s necessary.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Free File Converter I Keep Coming Back To: Fast, No Watermarks, and Supports 200+ Formats</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Mon, 20 Jul 2026 05:52:23 +0000</pubDate>
      <link>https://dev.to/emma-watson3/the-free-file-converter-i-keep-coming-back-to-fast-no-watermarks-and-supports-200-formats-59hd</link>
      <guid>https://dev.to/emma-watson3/the-free-file-converter-i-keep-coming-back-to-fast-no-watermarks-and-supports-200-formats-59hd</guid>
      <description>&lt;p&gt;File conversion is one of those tasks that seems simple but always ends up being a hassle. I've tried a dozen online converters, and most either have file size limits, require sign-ups, or are painfully slow. Recently, I needed to convert a batch of WebP images to PNG and a PDF to DOCX for a client. I found SerpSpur's All Type Free File Converter, and it handled both flawlessly. It supports over 200 formats, including CSV, DOCX, PDF, and WebP. The best part? No upload limits or watermarks. I converted a 50MB PDF in seconds, and the output was clean. It's also secure—no files are stored on their servers. If you deal with format conversions regularly, this is a solid tool to bookmark. Try it here: &lt;a href="https://serpspur.com/tool/all-type-free-file-converter/" rel="noopener noreferrer"&gt;https://serpspur.com/tool/all-type-free-file-converter/&lt;/a&gt;. It's fast, free, and actually works.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>From PDFs to Spreadsheets: My Go-To Workflow for Converting Invoices to CSV in Seconds</title>
      <dc:creator>Emma Watson</dc:creator>
      <pubDate>Wed, 08 Jul 2026 10:40:12 +0000</pubDate>
      <link>https://dev.to/emma-watson3/from-pdfs-to-spreadsheets-my-go-to-workflow-for-converting-invoices-to-csv-in-seconds-dpm</link>
      <guid>https://dev.to/emma-watson3/from-pdfs-to-spreadsheets-my-go-to-workflow-for-converting-invoices-to-csv-in-seconds-dpm</guid>
      <description>&lt;p&gt;I've been automating invoice processing for a side project, and one thing that always tripped me up was converting different formats to CSV. Whether it's a PDF from a vendor, an Excel sheet from a client, or an HTML table from a web app, you need a reliable way to extract data. Here's a bash script I use for quick conversions, plus a web tool for when I'm not in the terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmc1y6znujih6kjuveyjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmc1y6znujih6kjuveyjy.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
bash&lt;/p&gt;

&lt;h1&gt;
  
  
  !/bin/bash
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Convert all invoices in a folder to CSV
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Requires: python3, pandas, pdfplumber, openpyxl, lxml
&lt;/h1&gt;

&lt;p&gt;for file in invoices/&lt;em&gt;; do&lt;br&gt;
    ext="${file##&lt;/em&gt;.}"&lt;br&gt;
    case "$ext" in&lt;br&gt;
        pdf)&lt;br&gt;
            python3 -c "&lt;br&gt;
import pdfplumber, pandas as pd&lt;br&gt;
with pdfplumber.open('$file') as pdf:&lt;br&gt;
    rows = []&lt;br&gt;
    for page in pdf.pages:&lt;br&gt;
        table = page.extract_table()&lt;br&gt;
        if table:&lt;br&gt;
            rows.extend(table)&lt;br&gt;
df = pd.DataFrame(rows[1:], columns=rows[0])&lt;br&gt;
df.to_csv('${file%.&lt;em&gt;}.csv', index=False)&lt;br&gt;
print('Converted $file')&lt;br&gt;
"&lt;br&gt;
            ;;&lt;br&gt;
        xls|xlsx)&lt;br&gt;
            python3 -c "&lt;br&gt;
import pandas as pd&lt;br&gt;
df = pd.read_excel('$file', engine='openpyxl')&lt;br&gt;
df.to_csv('${file%.&lt;/em&gt;}.csv', index=False)&lt;br&gt;
print('Converted $file')&lt;br&gt;
"&lt;br&gt;
            ;;&lt;br&gt;
        html|htm)&lt;br&gt;
            python3 -c "&lt;br&gt;
import pandas as pd&lt;br&gt;
df = pd.read_html('$file')[0]&lt;br&gt;
df.to_csv('${file%.*}.csv', index=False)&lt;br&gt;
print('Converted $file')&lt;br&gt;
"&lt;br&gt;
            ;;&lt;br&gt;
        *)&lt;br&gt;
            echo "Skipping $file: unsupported format"&lt;br&gt;
            ;;&lt;br&gt;
    esac&lt;br&gt;
done&lt;/p&gt;

&lt;p&gt;This script works great for batch processing, but if you need a quick, one-off conversion without setting up dependencies, &lt;a href="https://serpspur.com/tool/invoice-pdf-to-csv-converter/" rel="noopener noreferrer"&gt;SERPSpur's Invoice to CSV Converter&lt;/a&gt; handles PDF, XLS, XLSX, and HTML instantly—no code required.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
