backlink Checked
Installation
Copy the prompt below and send it to your AI assistant (e.g. Claude Code) — it will follow the instructions and install automatically.
Install the "backlink" skill by following the instructions at https://skill123.me/install/backlink.
Run in your terminal — downloads and installs to ~/.claude/skills/.
curl -fsSL https://skill123.me/install/backlink.sh | bash
Download the zip and extract it into your skills directory (e.g. ~/.claude/skills/), then restart your session.
⬇ Download v1.0.14aa88b · 1.3 MBNot live-tested yet — this skill is rated on static analysis only.
About this skill
OpenCLI-first backlink discovery, profile analysis, opportunity qualification, safe browser-assisted form filling, evidence-based verification, and bulk data harvesting from logged-in dashboards. Use for backlinks, external links, competitor link research, blog-comment opportunities, directory submissions, Similarweb/Semrush/Ahrefs discovery, Search Console verification, anchor analysis, toxic-link review, disavow review, outreach templates, scraping SaaS report tables that have no API, driving the owner's logged-in Chrome from a script, or Chinese requests such as 反链、外链、找外链、发外链、评论外链、外链分析、抓后台数据、导出报表、数据面板、数据勘测. Also the vague forms users actually type:帮我搞点外链、去哪发外链、提交目录、批量提交、外链发出去没有、这些外链有没有毒、要不要 disavow、这个站有没有流量、值不值得发、竞品的外链哪来的、谁在给他导流、受众重合、Semrush 能查什么、Similarweb 能查什么、这个报表在哪、面板功能手册、平台手册、这页有没有数据、勘测一下这个页面、这个站没有 API 怎么取数.
<skill name="backlink" version="3.3" body-format="xml">
<why-xml>
The frontmatter above stays YAML because the Skill loader reads it for
discovery. Everything below is XML because this Skill is mostly laws and
routing, and a law that is easy to skim past is a law that gets broken. Tagged
blocks make "which rule did I just violate" answerable by name.
</why-xml>
<mission>
One business Skill for the complete backlink lifecycle. Do not split it back
apart, and do not create another browser-extension Skill — OpenCLI and its
Chrome extension are the connector underneath this Skill, never a separate
business workflow.
Two former Skills were merged in on 2026-08-16 and deleted: backlink-analyzer
(analysis templates, toxicity rubric, outreach — now in three references under
its original Apache-2.0 licence) and browser-harvest (pulling tables out of
logged-in dashboards — now <ref file="references/harvest.md"/>). The harvest
knowledge is general-purpose: ad platforms, e-commerce backends, any no-API
SaaS report. When a harvesting task has nothing to do with links, load this
Skill anyway and read that one reference.
</mission>
<map>
<summary>
Two things live here and they answer different questions. **The data files are
the asset; the references are how to use them and how not to fool yourself.**
</summary>
<tree><![CDATA[
backlink/
├── SKILL.md ← you are here: laws + routing + workflow entry points
├── CONTRIBUTING.md ← how to submit a PR, the data model, the evidence rule
│
├── data/ ← THE DATABASE. Machine-readable, PR-able, CI-checked.
│ ├── free-channels.json places that publish a link at no cost
│ ├── submission-targets.json routes that ACCEPT a submission — first-pass library
│ ├── paid-platforms.json platforms observed carrying purchased placements
│ ├── network-fingerprints.json known automation/PBN families; negative evidence, never placements
│ ├── index-submission.json engines that take a URL and publish NO link
│ └── schema/ JSON Schema for the files above
│
├── scripts/ ← run these; do not re-derive their knowledge by hand
│ ├── validate-data.mjs PR gate. CI runs exactly this. Must exit 0.
│ ├── validate-skill-xml.mjs the OTHER gate: SKILL.md body well-formed + every
│ │ <ref>/<law-ref> resolves. A bare <tag> in prose
│ │ silently unbalances the doc from that line on.
│ ├── self-test.mjs end-to-end smoke over the core scripts
│ ├── health.mjs run before ANY browser task
│ ├── opencli-core.mjs ★ defaultSession(), batchBrowser(), openAndEval(), run(), closeSession()
│ ├── lib-tools-share.mjs ★ the ONE panel launcher
│ ├── tools-share-open.mjs launch a tool by name; --goto for a deep link
│ ├── tools-share-node.mjs list a tool's nodes (read-only) or probe them one by
│ │ one — each node is a DIFFERENT shared account, so a node
│ │ capped on its daily report quota is fixed by switching node,
│ │ not by retrying
│ ├── similarweb-query.mjs performance | channels | similar-sites | audience-geo | site-keywords
│ ├── similarweb-keywords.mjs seed keyword → thousands of related keywords.
│ │ The keyword-research entry point the pipeline was missing.
│ │ Column-major DOM table; parsing lives in lib-similarweb.mjs
│ ├── similarweb-batch.mjs bulk traffic screen — one login, N domains, resumable;
│ │ emits evidence rows (value+stopReason+screenshot), no verdicts
│ ├── semrush-batch.mjs same, on the other card's quota (organic traffic)
│ ├── lib-batch-evidence.mjs the batch scripts' shared evidence contract — row shape,
│ │ completeness (resume) semantics, evidence-dir paths
│ ├── semrush-overview.mjs AS / organic traffic / ref-domains / keywords
│ ├── semrush-keyword.mjs global keyword detail plus one-session multi-country bulk plans
│ ├── semrush-report.mjs the OTHER five no-export reports (incl. referring-domains,
│ │ --rollup aggregates the rows THIS run fetched); reuses one
│ │ session; table reports paginate — pass --all-pages or it warns
│ ├── semrush-traffic.mjs Traffic & Market (.Trends) TOTAL visits — the only
│ │ Semrush number comparable with Similarweb. Runs
│ │ **foreground by default**, alone in this Skill:
│ │ the summary never hydrates if it *loads* hidden.
│ │ But "empty" has two unrelated causes with opposite
│ │ remedies — not hydrated vs never had a table — and
│ │ only the first is worth re-reading.
│ │ See <law-ref id="hidden-tabs-do-not-hydrate"/>
│ ├── traffic-crosscheck.mjs offline: eats one semrush-traffic.mjs JSON and one
│ │ similarweb-query.mjs JSON and reports the DIFFERENCES
│ │ between them — never an agree/diverge/conflict verdict,
│ │ never a non-zero exit for a big diff. How to read a gap:
│ │ references/traffic-screen.md. Never touches a page itself
│ ├── tools-share-evidence.mjs rendered, redacted evidence bundle for one report.
│ │ For a NEW capture prefer scripts/ground-truth.mjs (the
│ │ two-witness collector); come here for the REPORTS route
│ │ registry (which URL is which report) and for the wider
│ │ artifact set (html / ax / network / app-json)
│ ├── page-read.mjs render a public page → text, prices, paywall signal
│ │ spans (matched text + context, never verdict booleans)
│ ├── apply-traffic-screen.mjs write measured numbers + evidence paths back (never verdicts)
│ ├── inspect-page.mjs full form census (every form, every field, semantics +
│ │ markers) + scene evidence; fillable/blocker are marked
│ │ suggested — the AI judges from the census + screenshot
│ ├── safe-fill.mjs fill a reviewed payload, never submit; refusal exits
│ │ leave a captureScene pair first
│ ├── lib-evidence-scene.mjs ★ captureScene(): the ONE failure-scene contract —
│ │ piercing census + screenshot, paired, redacted, never
│ │ throws. Every browser script's failure branch calls it
│ │ BEFORE any close/exit (先取证后死、先取证后关).
│ │ Reuses ground-truth.mjs's CENSUS_EXPR verbatim.
│ ├── lib-deep-dom.mjs ★ the ONE shadow-DOM-piercing traversal. EVERY counting
│ │ probe goes through it. Measured 2026-08-29 on one page,
│ │ one instant: body.innerText 59 chars / deep text
│ │ 1,605,054 / 44 shadow roots. innerText and
│ │ querySelectorAll both stop at the shadow boundary, so
│ │ every table / cell / text count taken before this file
│ │ existed measured a sliver of the page. Emits the LIGHT
│ │ reading beside the deep one - the gap is the diagnostic.
│ │ Also holds the segment
Documentation
OpenCLI-first backlink discovery, profile analysis, opportunity qualification, safe browser-assisted form filling, evidence-based verification, and bulk data harvesting from logged-in dashboards. Use for backlinks, external links, competitor link research, blog-comment opportunities, directory submissions, Similarweb/Semrush/Ahrefs discovery, Search Console verification, anchor analysis, toxic-link review, disavow review, outreach templates, scraping SaaS report tables that have no API, driving the owner's logged-in Chrome from a script, or Chinese requests such as 反链、外链、找外链、发外链、评论外链、外链分析、抓后台数据、导出报表、数据面板、数据勘测. Also the vague forms users actually type:帮我搞点外链、去哪发外链、提交目录、批量提交、外链发出去没有、这些外链有没有毒、要不要 disavow、这个站有没有流量、值不值得发、竞品的外链哪来的、谁在给他导流、受众重合、Semrush 能查什么、Similarweb 能查什么、这个报表在哪、面板功能手册、平台手册、这页有没有数据、勘测一下这个页面、这个站没有 API 怎么取数.
<skill name="backlink" version="3.3" body-format="xml">
<why-xml>
The frontmatter above stays YAML because the Skill loader reads it for
discovery. Everything below is XML because this Skill is mostly laws and
routing, and a law that is easy to skim past is a law that gets broken. Tagged
blocks make "which rule did I just violate" answerable by name.
</why-xml>
<mission>
One business Skill for the complete backlink lifecycle. Do not split it back
apart, and do not create another browser-extension Skill — OpenCLI and its
Chrome extension are the connector underneath this Skill, never a separate
business workflow.
Two former Skills were merged in on 2026-08-16 and deleted: backlink-analyzer
(analysis templates, toxicity rubric, outreach — now in three references under
its original Apache-2.0 licence) and browser-harvest (pulling tables out of
logged-in dashboards — now <ref file="references/harvest.md"/>). The harvest
knowledge is general-purpose: ad platforms, e-commerce backends, any no-API
SaaS report. When a harvesting task has nothing to do with links, load this
Skill anyway and read that one reference.
</mission>
View full documentation
<map>
<summary>
Two things live here and they answer different questions. **The data files are
the asset; the references are how to use them and how not to fool yourself.**
</summary>
<tree><![CDATA[
backlink/
├── SKILL.md ← you are here: laws + routing + workflow entry points
├── CONTRIBUTING.md ← how to submit a PR, the data model, the evidence rule
│
├── data/ ← THE DATABASE. Machine-readable, PR-able, CI-checked.
│ ├── free-channels.json places that publish a link at no cost
│ ├── submission-targets.json routes that ACCEPT a submission — first-pass library
│ ├── paid-platforms.json platforms observed carrying purchased placements
│ ├── network-fingerprints.json known automation/PBN families; negative evidence, never placements
│ ├── index-submission.json engines that take a URL and publish NO link
│ └── schema/ JSON Schema for the files above
│
├── scripts/ ← run these; do not re-derive their knowledge by hand
│ ├── validate-data.mjs PR gate. CI runs exactly this. Must exit 0.
│ ├── validate-skill-xml.mjs the OTHER gate: SKILL.md body well-formed + every
│ │ <ref>/<law-ref> resolves. A bare <tag> in prose
│ │ silently unbalances the doc from that line on.
│ ├── self-test.mjs end-to-end smoke over the core scripts
│ ├── health.mjs run before ANY browser task
│ ├── opencli-core.mjs ★ defaultSession(), batchBrowser(), openAndEval(), run(), closeSession()
│ ├── lib-tools-share.mjs ★ the ONE panel launcher
│ ├── tools-share-open.mjs launch a tool by name; --goto for a deep link
│ ├── tools-share-node.mjs list a tool's nodes (read-only) or probe them one by
│ │ one — each node is a DIFFERENT shared account, so a node
│ │ capped on its daily report quota is fixed by switching node,
│ │ not by retrying
│ ├── similarweb-query.mjs performance | channels | similar-sites | audience-geo | site-keywords
│ ├── similarweb-keywords.mjs seed keyword → thousands of related keywords.
│ │ The keyword-research entry point the pipeline was missing.
│ │ Column-major DOM table; parsing lives in lib-similarweb.mjs
│ ├── similarweb-batch.mjs bulk traffic screen — one login, N domains, resumable;
│ │ emits evidence rows (value+stopReason+screenshot), no verdicts
│ ├── semrush-batch.mjs same, on the other card's quota (organic traffic)
│ ├── lib-batch-evidence.mjs the batch scripts' shared evidence contract — row shape,
│ │ completeness (resume) semantics, evidence-dir paths
│ ├── semrush-overview.mjs AS / organic traffic / ref-domains / keywords
│ ├── semrush-keyword.mjs global keyword detail plus one-session multi-country bulk plans
│ ├── semrush-report.mjs the OTHER five no-export reports (incl. referring-domains,
│ │ --rollup aggregates the rows THIS run fetched); reuses one
│ │ session; table reports paginate — pass --all-pages or it warns
│ ├── semrush-traffic.mjs Traffic & Market (.Trends) TOTAL visits — the only
│ │ Semrush number comparable with Similarweb. Runs
│ │ **foreground by default**, alone in this Skill:
│ │ the summary never hydrates if it *loads* hidden.
│ │ But "empty" has two unrelated causes with opposite
│ │ remedies — not hydrated vs never had a table — and
│ │ only the first is worth re-reading.
│ │ See <law-ref id="hidden-tabs-do-not-hydrate"/>
│ ├── traffic-crosscheck.mjs offline: eats one semrush-traffic.mjs JSON and one
│ │ similarweb-query.mjs JSON and reports the DIFFERENCES
│ │ between them — never an agree/diverge/conflict verdict,
│ │ never a non-zero exit for a big diff. How to read a gap:
│ │ references/traffic-screen.md. Never touches a page itself
│ ├── tools-share-evidence.mjs rendered, redacted evidence bundle for one report.
│ │ For a NEW capture prefer scripts/ground-truth.mjs (the
│ │ two-witness collector); come here for the REPORTS route
│ │ registry (which URL is which report) and for the wider
│ │ artifact set (html / ax / network / app-json)
│ ├── page-read.mjs render a public page → text, prices, paywall signal
│ │ spans (matched text + context, never verdict booleans)
│ ├── apply-traffic-screen.mjs write measured numbers + evidence paths back (never verdicts)
│ ├── inspect-page.mjs full form census (every form, every field, semantics +
│ │ markers) + scene evidence; fillable/blocker are marked
│ │ suggested — the AI judges from the census + screenshot
│ ├── safe-fill.mjs fill a reviewed payload, never submit; refusal exits
│ │ leave a captureScene pair first
│ ├── lib-evidence-scene.mjs ★ captureScene(): the ONE failure-scene contract —
│ │ piercing census + screenshot, paired, redacted, never
│ │ throws. Every browser script's failure branch calls it
│ │ BEFORE any close/exit (先取证后死、先取证后关).
│ │ Reuses ground-truth.mjs's CENSUS_EXPR verbatim.
│ ├── lib-deep-dom.mjs ★ the ONE shadow-DOM-piercing traversal. EVERY counting
│ │ probe goes through it. Measured 2026-08-29 on one page,
│ │ one instant: body.innerText 59 chars / deep text
│ │ 1,605,054 / 44 shadow roots. innerText and
│ │ querySelectorAll both stop at the shadow boundary, so
│ │ every table / cell / text count taken before this file
│ │ existed measured a sliver of the page. Emits the LIGHT
│ │ reading beside the deep one - the gap is the diagnostic.
│ │ Also holds the segment
Score breakdown
Assessment methodology
Version history
— Refreshed from GitHub yan-labs/yan-skills@14aa88b
Imported from yan-labs/yan-skills@main