WHOLE ANTIDETECT CATALOG
============================================================================

2ND ED., 1ST PRINTING. Corrected to 2026-08-14.
Field check 2026-08-14T09:12:00Z. 153 entries in 10 sections.
Published at https://awesomeantidetect.com/data/ under CC0-1.0 — public domain, no attribution required.

WHAT THIS IS
----------------------------------------------------------------------------
A register of anti-detect browsers, stealth automation patches, detection test
pages, fingerprinting and TLS libraries, papers, datasets and the anti-bot
vendors on the other side of the problem. Every entry carries a licence, a
maintenance state and the dated fields that state was derived from.

The maintenance state is DERIVED, never asserted, never supplied by whoever
submitted the entry. Recompute it from the measured columns and this file must
agree with the printed page; where it does not, the register is wrong and the
correction is issued as an errata leaf against a named edition.

This file contains no score, no percentile, no rarity figure and no comparison
against any population of tools, because this register has measured none.
It contains no detection-test results: no entry here has been run against any
anti-bot vendor by this register.

FILES
----------------------------------------------------------------------------
  registry.json   the whole payload, header + schema + sections + entries
  registry.csv    one row per entry, columns in the order printed below
  README.md       this file

EDITIONS AND PRINTINGS
----------------------------------------------------------------------------
A new EDITION when a threshold, a source field or an endpoint changes — when
the rule changes. A new PRINTING when only the data is re-swept — when the
world changes. The two numbers answer two different questions, and every row
carries the field check instant it was read at.

Rubric in force: Second edition, since 2026-08-14.
Printed in full at https://awesomeantidetect.com/method/ ; the superseded first edition stays in
print at https://awesomeantidetect.com/method/1/ so any state it set can be audited against it.

THE THRESHOLDS THAT PRODUCE A STATE
----------------------------------------------------------------------------
  DEAD
      the last HTTP check returned 400 or worse, or did not complete — or the
      repository has no push within 1095 days

  WITHDRAWN
      the URL answers with a permanent redirect to another entry

  ARCHIVED
      GitHub archived flag is true

  NRND
      pushed 365–1095 days before the field check — or pushed more than 180
      days ago while an entry in this registry declares it superseded and that
      successor is ACTIVE

  SEMI
      pushed 90–365 days before the field check

  ACTIVE
      pushed within 90 days of the field check

  Fallback when pushed_at was not captured
      the latest release date stands in for the push date

  Non-repository entries
      state comes from the HTTP check alone: 200–399 is ACTIVE, 400 and worse
      is DEAD

SCHEMA
----------------------------------------------------------------------------
Provenance classes:
  MEASURED
      Read from the endpoint named beside it, at the field-check instant.
      Never guessed: a field the sweep did not capture is null.
  DERIVED
      Computed from measured fields by the rubric in force. Recomputable
      from this same file; nothing here is stored by hand.
  TRANSCRIBED
      Copied from the source itself — its own name, its own URL, its own
      words condensed to one sentence. Not a claim this register makes.
  EDITORIAL
      The curator's decision: placement, keying, declared relations, flags
      and the signed annotation. The only opinion in the payload.

15 of the 38 columns carry a fetch date: they are readings taken
at checked_at and at no other instant. They are marked [dated] below.
A field the sweep did not capture is null. It is never guessed.

  slug  (string)  [editorial]
      source: Curator, signed
      The key this entry is filed under. Stable across printings; a slug is
      never reused for a different project.

  name  (string)  [transcribed]
      source: The project, at its own URL
      Spelled as the project spells it, including capitalisation the
      register would otherwise normalise.

  url  (string)  [transcribed]
      source: The project, at its own URL
      The exact URL the link check was made against. Where a vendor host
      refuses automated clients, this is the docs host and the substitution
      is carried in flags.

  section  (string (01–10))  [editorial]
      source: Curator, signed
      One of ten sections. An entry sits in exactly one; cross-topic entries
      are placed where a reader would look first, not where they fit best.

  section_slug  (string)  [editorial]
      source: Curator, signed
      The section's URL segment, so a row can be joined back to its printed
      section without a lookup table.

  kind  (repo | page | docs | paper | dataset | community | product)  [editorial]
      source: Curator, signed
      What sort of thing this is, which decides which fields can exist at
      all: only a repo carries pushed_at, only a non-repo is stated by the
      link check alone.

  description  (string)  [transcribed]
      source: The project's README, docs or abstract
      One sentence, condensed from what the source says about itself. It is
      never a finding, an endorsement or a test result.

  language  (string | null)  [transcribed]
      source: The project, at its own URL
      Implementation language as the project states it, not as GitHub's
      linguist guesses it.

  repo_path  (string | null)  [measured]
      source: GET https://api.github.com/repos/{owner}/{repo}
      owner/name as it appears in the API path. Null for every entry with no
      repository, which is what makes the rest of the repository columns
      null too.

  pushed_at  (date | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → pushed_at
      The liveness field. Null where the sweep did not capture it, in which
      case the rubric's fallback clause reads release_published_at instead
      and says so in derivation.

  created_at  (date | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → created_at
      Used only as the denominator of stars_per_day. It sets no state.

  stars  (integer | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → stargazers_count
      A reading taken at one instant, not a live figure, and it sets no
      state. It is the least important number in the row.

  forks  (integer | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → forks_count
      Captured where the sweep recorded it. Sets no state.

  archived  (boolean | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → archived
      A maintainer's own statement, and the one measured field that outranks
      every date rule.

  archived_at  (date | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → archived_at
      Captured where GitHub returned it. Its absence never implies the
      archive flag is false — read archived for that.

  release_tag  (string | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo}/releases/latest → tag_name
      The latest tagged release as the project tagged it. Null is ambiguous
      on its own, which is why no_releases exists.

  release_published_at  (date | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo}/releases/latest → published_at
      Stands in for pushed_at under the fallback clause. Where it does,
      derivation names the substitution.

  no_releases  (boolean)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo}/releases/latest → 404
      True means the repository has published no tagged release at all.
      False with a null release_tag means the sweep did not capture one — a
      different thing, kept a different field.

  http_status  (integer | null)  [measured] [dated]
      source: HEAD, then GET on failure, against url — redirects not followed
      0 means the request did not complete at all. Any status of 400 or
      worse is tested first and produces DEAD, because an unreachable URL
      cannot be rescued by another field.

  http_checked_at  (timestamp | null)  [measured] [dated]
      source: HEAD, then GET on failure, against url — redirects not followed
      The instant the link check was made. Equal to checked_at in this
      printing, and carried per row so a later partial re-sweep cannot lie
      about it.

  http_note  (string | null)  [measured] [dated]
      source: HEAD, then GET on failure, against url — redirects not followed
      What the non-200 was: the response, the redirect target, or the
      failure mode. Printed verbatim on the field log.

  http_redirect_to  (string | null)  [measured] [dated]
      source: HEAD, then GET on failure, against url — redirects not followed → Location
      Where a 301 pointed. This is the whole evidence for WITHDRAWN: the
      maintainer said where the work went, and the register did not infer
      it.

  license_spdx  (string | null)  [measured] [dated]
      source: GET https://api.github.com/repos/{owner}/{repo} → license.spdx_id
      Null means no licence is declared, which is a finding rather than a
      gap — see license_bucket. NOASSERTION means a licence file exists that
      SPDX could not identify.

  license_bucket  (permissive | copyleft | custom | none | na)  [derived]
      source: licenseBucket(), from license_spdx
      none is the one that matters: an entry you cannot legally reuse. na is
      for entries with no source to license, such as a test page.

  state  (ACTIVE | SEMI | NRND | WITHDRAWN | ARCHIVED | DEAD)  [derived]
      source: Rubric, second edition, thresholds in force
      Never stored, never asserted, never supplied by a submitter. Recompute
      it from the measured columns and this file must agree with the printed
      page.

  state_first_edition  (string)  [derived]
      source: Rubric, first edition (superseded)
      The same field data put through the superseded rules. Where it differs
      from state, the difference is a property of the rules and not of the
      world.

  state_moved  (boolean)  [derived]
      source: state ≠ state_first_edition
      True for every row printed on the errata leaf for this printing.

  derivation  (string)  [derived]
      source: Rubric, second edition, the clause that fired
      The rule that set the state, in the rubric's own words, with the
      values it read quoted inside it. This column is the audit trail.

  age_days  (integer | null)  [derived]
      source: checked_at − the liveness field
      Whole days between the liveness field and the field check. Measured
      against the printing's instant, never against the reader's clock, so a
      page reprints identically in a year.

  release_bucket  (r30 | r180 | r365 | rold | rnone | runknown)  [derived]
      source: release_published_at, bucketed
      The recency facet the filter rail counts against. runknown is not
      rnone: one means unread, the other means none exists.

  stars_per_day  (number | null)  [derived]
      source: stars ÷ age of created_at
      Two measured numbers divided. Not a rank, not a score, not a
      comparison against any population of tools — this register has
      measured none.

  verify_independently  (boolean)  [derived]
      source: stars_per_day > 25
      The unverified flag, and the only place this register raises an
      eyebrow in a column. It changes no state and accuses nothing; it says
      check the contributor graph yourself.

  flags  (string[])  [editorial]
      source: Curator, signed
      Conditions the reader should know before trusting the row: young-repo,
      vendor-operated, freemium, historical, listed-elsewhere,
      docs-host-substituted, no-license.

  supersedes  (string[] (slugs))  [editorial]
      source: Curator, signed
      Declared, not inferred. Both directions are stored once and reversed
      at build, so the graph cannot contradict itself.

  superseded_by  (string[] (slugs))  [editorial]
      source: Curator, signed
      Feeds one rubric clause: a quiet entry whose declared successor reads
      ACTIVE is marked NRND rather than left looking healthy.

  alternative_to  (string[] (slugs))  [editorial]
      source: Curator, signed
      Symmetric. Substitutes for the same job, with no claim that either is
      better.

  annotation  (string | null)  [editorial]
      source: Curator, signed
      The signed verdict, printed in italic typewriter face and kept
      separate from every other column precisely so it can be ignored.

  checked_at  (timestamp)  [measured] [dated]
      source: The sweep's own clock
      The instant every dated field in this row was read. It is the same
      value on every row of this printing, and it is the only claim this
      file makes about how current it is.

CONTRIBUTING
----------------------------------------------------------------------------
Entry criteria, the submission form and the exact row format: https://awesomeantidetect.com/submit/
A submission carries measurable fields only. No submitter sets a state; the
rubric does, from the fields, at the next sweep.

LICENCE
----------------------------------------------------------------------------
CC0-1.0. To the extent possible under law, the keepers of this register have
waived all copyright and related rights to the data in these files. No
attribution is required. The projects listed are under their own licences,
recorded in license_spdx, and this waiver says nothing about them.

Cite as: WHOLE ANTIDETECT CATALOG, 2ND ED., 1ST PRINTING, corrected to 2026-08-14.
