A zero-dependency Node.js pipeline for building Google disavow files you can actually trust.
Built by It All Started With A Idea LLC · AHMEEGO · Maintained by John Williams
Toxicity scores lie in both directions. In production use, this pipeline found an obvious spam blog scoring 28/100 ("clean") while Linktree — a platform used by millions of legitimate creators — scored 58/100 ("toxic"). A disavow file built from scores alone cuts real links and keeps junk. A disavow file built by opening 100 tabs takes all day.
This tool splits the difference: automate everything verifiable, verify everything live, and reserve human judgment for the handful of domains that actually need it. In a real engagement it verified 97 contested domains in about two minutes and surfaced two cloned copies of the client's website that no score would have flagged.
The disavow tool is one-directional and Google provides no API for uploading — so the pipeline treats the final upload as a deliberate human act, and makes everything before it fast, repeatable, and documented.
Node.js 18+ (uses built-in fetch). No npm installs. Works on macOS, Linux, and Windows.
node disavow-check.js all candidate-disavow.txt semrush-export.csv
# review probe-results.csv, fill the verdict column (disavow|keep)
node disavow-check.js finalize candidate-disavow.txt probe-results.csv \
--domain example.com --client "Client Name" --author "Your Name"Output: a dated, validated, upload-ready disavow-final-YYYY-MM-DD.txt, a client-ready disavow-report-YYYY-MM-DD.md, and archived copies of both.
| Stage | Command | What it does | Why |
|---|---|---|---|
| 1. Validate | validate <file> |
Syntax, duplicates, encoding, GSC size limits, protected-domain screen, brand-lookalike alerts | A malformed file is silently mishandled by Google; a protected domain in the file is the worst failure mode |
| 2. Crosscheck | crosscheck <file> <semrush.csv> |
Reconciles entries against SEMrush toxicity scores in both directions | Forward check justifies what's in; reverse check catches toxic domains you missed |
| 3. Probe | probe <file> [--active] |
Live HTTP verification of every contested domain: status, page title, parked/for-sale detection. Writes probe-results.csv with suggested verdicts |
Scores are heuristics; page content is evidence. Dead and parked domains auto-resolve, leaving only live sites for human review |
| 4. Adjudicate | (you, in a spreadsheet) | Fill disavow or keep for the remaining rows |
The judgment layer no script should own |
| 5. Finalize | finalize <file> <verdicts.csv> [--existing old.txt] |
Promotes confirmed domains, merges any prior GSC file (uploads replace, not append), strips protected domains, writes dated output + report + archive | Auditability: six months from now, you'll know exactly what was submitted and why |
- Tie-breaker: ambiguous domains are kept. A wrongly disavowed real link causes measurable harm; a wrongly retained spam link is already discounted by Google.
- Protected list is a hard stop. Domains in
protected.txtcan never reach the final file. - Brand lookalikes get flagged, not auto-cut.
wellandgood.blogmight be a spam clone of a real publication — or an affiliated property. The tool flags; you decide. - Everything unresolved stays out. No verdict, no disavow.
From real production runs: cloned copies of the client's website serving scraped content with injected casino links · "aged domains and backlinks for sale" storefronts · parked/for-sale pages · dead domains with expired certs · legitimate small businesses that scores punished for low authority.
Do I even need a disavow file? Usually no — Google says its systems ignore most spam links, and disavow is primarily for manual actions and known purchased links. But manufactured link networks and cloned-content domains are exactly what the tool exists for, and a clean profile matters more as AI answer engines lean on authority signals. See the wiki for the full discussion.
Can this upload to Search Console for me? No — nobody can. Google provides no disavow API by design. The final upload is manual at search.google.com/search-console/disavow-links.
What export does crosscheck expect? A SEMrush Backlink Audit CSV (it contains toxicity scores). Column detection is flexible — it finds domain/URL, toxicity, and authority columns by header.
MIT. Use it, fork it, ship it. See LICENSE.
Part of the open-source tooling family from AHMEEGO — see also the Google Ads MCP Server and googleadsagent.ai.