DEV Community

Chetan Sanghani
Chetan Sanghani

Posted on

Medium and GitHub both went nofollow — so I built a 40-line PowerShell backlink verifier

I burned about 30 minutes of work on Monday shipping content to Medium and GitHub in the belief they'd give me dofollow backlinks. Both turned out to be platform-wide nofollow. Both discoveries came from a single curl command that I should have run before the work, not after.

This post is: (1) the two discoveries and why the standard SEO guidance is now stale, (2) the 40-line PowerShell verifier I wrote so I never make the mistake again, and (3) the specific header dance you need to actually get past bot-detection on Medium and Quora.

What "dofollow" means, and why it moves

Every <a href="..."> on the web is either dofollow or nofollow. Google (and other search engines) treats them very differently:

  • Dofollow (rel doesn't contain nofollow / ugc / sponsored): the source domain vouches for the destination. Passes SEO "link equity." Counts toward how Google decides the destination's ranking authority.
  • Nofollow / UGC / Sponsored: the source domain explicitly declines to vouch. Google largely discounts these for ranking purposes. Still useful for referral traffic and brand exposure, but doesn't move the SEO needle.

For an AdSense-approval situation like mine — where reviewers look at "does this site have external validation from real sources" — dofollow domains matter. Nofollow domains are decorative.

Now the catch: platforms shift policies. What was dofollow in 2020 may be nofollow today, and cached SEO guides from a few years back get you the outdated answer.

Discovery 1: Medium is now ugc nofollow

I republished a Section 24(b) home-loan article on Medium, expecting the author-bio + in-article links to be dofollow (per most SEO guides from 2020-2022). Curl'd the live article:

curl -sL "https://medium.com/@author/article-slug" `
  -A "Mozilla/5.0" | Select-String -Pattern 'smarttaxcalc'
Enter fullscreen mode Exit fullscreen mode

Result on every anchor:

<a class="z rm" href="https://smarttaxcalc.in/..." rel="noopener ugc nofollow" target="_blank">
Enter fullscreen mode Exit fullscreen mode

That rel="noopener ugc nofollow" is Medium's current default — they rolled it out platform-wide around 2023-2024 to kill SEO spam. Every outbound link on Medium is now nofollow, including your author-bio link. Google discounts them all.

Discovery 2: GitHub READMEs are nofollow too — even in your own fork

Same day, I forked an "awesome-personal-finance" repo, added SmartTaxCalc to the list, and pushed. Standard SEO advice says: "even if the PR isn't merged, your fork at github.com/YOUR-USER/awesome-XXX/README.md still has the anchor to your site — that's a dofollow link from github.com."

Wrong, at least since ~2020. Curl the rendered README:

<a href="https://mint.intuit.com/" rel="nofollow">Mint</a>
<a href="https://smarttaxcalc.in" rel="nofollow">SmartTaxCalc</a>
Enter fullscreen mode Exit fullscreen mode

Every external anchor on any GitHub-rendered README is rel="nofollow". GitHub applies this platform-wide to reduce link-farming via repo forks. Even Mint on the upstream repo (a heavily authoritative domain in the fintech space) is nofollow. There's nothing you can do to force it dofollow.

Both discoveries invalidated ~30 minutes of preparation work in the same afternoon. The Medium article was still worth publishing (referral traffic + canonical protection so Medium doesn't outrank the original), but I wouldn't have spent time on the GitHub PR pack if I'd known.

The lesson: curl before you write

Both would have been caught by a 30-second check before the work: fetch any existing outbound link on the target platform, look at its rel attribute. If it contains nofollow, that's the platform's blanket policy — no author, no article, no PR can override it.

But I don't want to remember to do this manually every time. So I wrote it into my weekly analytics script. Every Sunday, along with GSC/GA4/Bing exports, the script now curls every referring URL I care about and reports which anchors are dofollow vs nofollow.

The verifier — 40 lines of PowerShell

The core loop, minus try/catch scaffolding:

$siteHost = ([Uri]$config.siteUrl).Host   # e.g. "smarttaxcalc.in"

foreach ($src in $config.knownReferringUrls) {
    $resp = Invoke-WebRequest -Uri $src -UseBasicParsing -TimeoutSec 20 `
        -Headers $browserHeaders   # see next section for the header set

    # Match every anchor pointing to our host
    $pattern = '<a[^>]*href="[^"]*' + [regex]::Escape($siteHost) + '[^"]*"[^>]*>'
    $anchors = [regex]::Matches($resp.Content, $pattern,
                [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)

    foreach ($m in $anchors) {
        $tag = $m.Value
        $rel = if ($tag -match 'rel="([^"]*)"') { $Matches[1] } else { '' }

        # Dofollow = no nofollow, no ugc, no sponsored in rel.
        # rel="noopener noreferrer" is fine — it's a security attribute, not SEO.
        $isDofollow = -not ($rel.ToLower() -match '\b(nofollow|ugc|sponsored)\b')

        [pscustomobject]@{
            sourceUrl  = $src
            rel        = $rel
            isDofollow = $isDofollow
        }
    }
    Start-Sleep -Milliseconds 500   # polite pause between hosts
}
Enter fullscreen mode Exit fullscreen mode

config.knownReferringUrls is just a list of URLs where you've published or shared a link back to your site — Medium article URLs, Quora answer URLs, Dev.to posts, forum posts, whatever.

Output goes into a CSV (backlink-rel-verification.csv) and — this is where it stops being just a report — feeds a scorecard row in my weekly insights.md:

| Dofollow referring domains | 1 | ≥ 5 | 🔴 |
Enter fullscreen mode Exit fullscreen mode

If Medium ever does switch back to dofollow (unlikely), or a new post I published turns out to be a hidden dofollow win, I'll see it in Sunday's report without doing anything. Same in reverse: if a platform I currently count as dofollow shifts to nofollow silently, the scorecard row updates.

The header dance for Medium and Quora

The naive Invoke-WebRequest -Uri $url -UseBasicParsing gets 403'd immediately on Medium, Quora, and any Cloudflare-fronted site. Even adding -UserAgent 'Mozilla/5.0' isn't enough — they check other headers too.

This is the header set that gets me through most sites:

$browserHeaders = @{
    'User-Agent'                = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
    'Accept'                    = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'
    'Accept-Language'           = 'en-US,en;q=0.9'
    'Accept-Encoding'           = 'gzip, deflate, br'
    'Sec-Ch-Ua'                 = '"Chromium";v="121", "Not A(Brand";v="99"'
    'Sec-Ch-Ua-Mobile'          = '?0'
    'Sec-Ch-Ua-Platform'        = '"Windows"'
    'Sec-Fetch-Dest'            = 'document'
    'Sec-Fetch-Mode'            = 'navigate'
    'Sec-Fetch-Site'            = 'none'
    'Sec-Fetch-User'            = '?1'
    'Upgrade-Insecure-Requests' = '1'
}
Enter fullscreen mode Exit fullscreen mode

The Sec-Ch-Ua* and Sec-Fetch-* headers are what Chrome sends automatically that a bare HTTP client doesn't. Without them, Cloudflare's bot detection has a very high true-positive rate on your requests.

Even with the full set, Medium and Quora still block on my Windows box — probably a TLS fingerprint check that Invoke-WebRequest can't spoof (curl.exe fails the same way). For those, the verifier reports ❓ Unknown (fetch blocked) rather than misclassifying as nofollow. When it can't confirm, it says so.

What the scorecard actually shows

Running against 6 known referring URLs — 3 Dev.to articles, 1 Medium republish, 1 GitHub Awesome-List fork, 1 Quora answer:

| Source     | Rel                     | Dofollow?               |
|------------|-------------------------|-------------------------|
| dev.to     | noopener noreferrer     | ✅ Yes (x10 anchors)    |
| medium.com | (fetch blocked 403)     | ❓ Unknown              |
| github.com | nofollow                | ❌ No                   |
| quora.com  | (fetch blocked 403)     | ❓ Unknown              |
Enter fullscreen mode Exit fullscreen mode

Unique dofollow referring domains: 1 (dev.to). Both Medium and GitHub, which I thought would boost this count to 3, contribute zero. The Quora and Medium fetch blocks aren't a huge loss — I already know from a prior manual curl (on a Linux box with a different TLS fingerprint) that both are nofollow.

Why this matters more than a one-off check

Two reasons.

One: platform policies drift, and you find out via ranking drops rather than an announcement. LinkedIn made outbound links nofollow around 2016. Twitter went nofollow in 2019. Medium moved to ugc nofollow around 2023-2024. Quora went nofollow-by-default in 2022. GitHub went nofollow on README external links around 2020. The pattern is one-way — platforms don't go back to dofollow. Any pre-2023 SEO guide you're reading is potentially wrong about at least one of these.

Two: if you publish enough content across enough platforms, you lose track. I have 3 Dev.to articles, 2 Quora answers, 34 LinkedIn Company Page posts, 1 Medium republish, and 1 GitHub fork. Manually curling each one every Sunday to check the rel attribute is real work. Encoding it into the analytics script — 40 lines of PowerShell — means it becomes a green/red row on the weekly report, and I only pay attention when something changes.

Steal the pattern

The full script lives in SmartTaxCalc's analytics folder (search for BACKLINK REL-ATTRIBUTE VERIFIER). It runs alongside GSC / GA4 / Bing / PageSpeed fetches — one script, one double-click, all your marketing signals in one place.

Two changes to make it fit your setup:

  1. Change $config.siteUrl and $config.knownReferringUrls to your domain + your list
  2. Depending on your platform mix, you might want to add retry logic for the 403-heavy platforms — I chose to just report them as Unknown because I already know their policies

If you're an indie hacker or solo founder shipping content to multiple platforms and hoping some of them count toward your SEO signal, run this once a week and stop being surprised.


I'm Chetan Sanghani, building SmartTaxCalc.in — a free, browser-based Indian tax + finance calculator platform. Previously wrote about Google's MathSolver JSON-LD validator quirks, dropping mobile LCP under 2s on Blazor WASM, and a self-cleaning Product Hunt teaser banner.

Top comments (0)