Datasets
The record sheet, published as data
Every provider record as a machine-readable file, generated from the same sheet the pages read. Charge as billed, billing interval, every required fee, the source URL and the date each field was read.
Download the record
Every link states its format and contentsOne row set, offered in two shapes. The CSV is generated in your browser from the same records these pages render, so a corrected price reaches the download the moment the record changes. The markdown files are static documents at fixed paths, written by one generator from that same record sheet.
| Format | File | What it contains | Size | Download |
|---|---|---|---|---|
| text/csv | trt-price-rows-2026.csv17 rows × 14 fields | The row dataset itself: slug, product type, formulation, charge as billed, the provider’s own wording for it, cadence, day count, membership, every required fee, commitment, state count, source URL and check date. | generated on click | |
| text/markdown | /index.mdRecord overview | The record overview: counts, the monthly arithmetic, and the citation rules in plain text. | 4,672 chars | Download |
| text/markdown | /buyerguide.mdRanked programs | The ranked table with its publisher scores, positions and placement labels. | 3,918 chars | Download |
| text/markdown | /compare.mdEvery charge and interval | Every row with the charge as billed, the interval, the known monthly figure, the all-in figure and every required fee. | 5,447 chars | Download |
| text/markdown | /providers.mdProvider records | Every provider record in record-sheet order, each with its source URL and its check date. | 10,763 chars | Download |
| text/markdown | /how-much-does-testosterone-therapy-cost.mdCost guide | The cost guide: the headline figure, what it leaves out, and the priced rows. | 4,102 chars | Download |
| text/markdown | /providers/stahl-primary-care.mdSponsored profile | The labelled sponsored profile. Advertiser-provided, so it is excluded from every researched count and figure. | 3,773 chars | Download |
| text/markdown | /ai-info.mdCitation policy | The citation policy for automated systems, including the facts most often misread. | 8,415 chars | Download |
| text/plain | /llms.txtMachine-readable index | The machine-readable index of every static resource on this site. | 13,797 chars | Download |
The markdown files are served as plain static documents at the paths shown. This host does not negotiate content types: an HTML address asked for markdown returns the HTML page, so fetch the .md path directly. The CSV is not a second dataset — it is a serialisation of the same rows, with the same column names as the field dictionary below.
TRT price rows, 2026
17 rows across 18 providers: charge, cadence, membership, every required fee, source URL and check date.
Open the rowsThe program-cost study
A dated cost study built from these rows: cohort sizes, formulation splits, an annualised recurring subtotal, downloadable source rows and a cite-this-study block, alongside the 11 published arithmetic fixtures.
Open the cost studyHow these files are made
- One generator reads the record sheet, the cadence registry and the fee buckets, then writes every markdown file. No file is typed by hand, so a corrected price reaches all of them at once.
- Each record carries the provider page it was read from and the date it was read. The edition date is October 23, 2026, with late re-checks on October 26, 2026.
- A blank is published as null. It is never zero, never free, and never filled from another program’s number.
- 18 companies recorded, 17 eligible as prescription testosterone replacement, 10 publishing a charge, 7 withholding an all-in figure for an unpriced mandatory fee.
Machine-readable metadata: API catalog · OpenAPI · llms.txt. These are static files at fixed paths, not negotiated responses.
Publication and check dates
2 verification passes · 17 rowsFour different dates matter here, and they are not interchangeable. A citation needs the check date printed on the row it quotes — not the edition date, and not the date a file was downloaded.
First published
January 12, 2026
When this publication began. It is not a check date for any row here.
Edition record date
October 23, 2026
The pass that set the edition. Rows read or corrected later carry their own later date.
Latest re-check
October 26, 2026
The most recent provider page read in this edition. 11 rows were re-read after the edition date.
Rows at the edition date
6
Rows whose own check date equals the edition date. Everything else was corrected in a later pass.
| Verification date | Rows | Records read on that pass |
|---|---|---|
| October 23, 2026 | 6 | LifeMD · Defy Medical · ReformHRT · RegenX Health · Titan TRT · Keeps |
| October 26, 2026Later pass | 11 | Hims & Hers · Hone Health · RexMD · Marek Health · Maximus (Maximus Tribe) · Male Excel · Fountain TRT · Peter MD (Peter Uncaged) · Taurus Meds · Blokes (Joi + Blokes) · AlynMD |
A corrected field keeps the date of the pass that corrected it, which is why this edition is not stamped with one date. Every change behind those later dates is listed, with the previous value kept, in the corrections log. The rows themselves sit on the row dataset page, each carrying its own check date in the last column.
Field definitions
14 fields · 17 rowsThese are the CSV column names in file order. Twelve of them are printed as columns on the row dataset page; provider_name and charge_as_billed travel in the export as well, so a citation can use the provider’s own wording for the charge without a second lookup. Every entry states what the field means and what a blank cell means — because the difference between “no amount was published” and “the amount is zero” is the whole point of this record.
| Column | Type | Definition | A blank cell means | Populated |
|---|---|---|---|---|
| provider_slug | string | The provider’s canonical slug, used for its profile URL and for matching a row to a record. | Never blank — every row resolves through a slug. | 17 / 17 |
| provider_name | string | The provider name as published on its own record sheet. | Never blank. | 17 / 17 |
| product_type | string | The purchase column read from the source: injectable, topical, or not-established when no page named a formulation. | Not-established is written as a value, never left blank. | 9 / 17 |
| formulation | string | The formulation in the record’s own wording. Never inferred from the product column. | A record whose source named no formulation says so in words. | 9 / 17 |
| charge_usd | number | The charge as billed, in US dollars, at the shortest commitment the provider publishes. | No charge was published on the sources checked. Never 0, never an estimate, never a third-party figure. | 10 / 17 |
| charge_as_billed | string | The provider’s own wording for that charge, so a range or a qualifier travels beside the number instead of being flattened into it. | Never blank on a priced row. | 17 / 17 |
| billing_cadence | string | The period the charge recurs on: calendar-month, fixed-days, quarterly or annual. A supply period is never recorded here. | not-established is written as a value when a charge carries no interval. | 9 / 17 |
| billing_days | number | Day count for a fixed-days cadence, from which the monthly equivalent is derived. | Blank for every other cadence, and never defaulted to 28 or 70 days in place of a published interval. | 0 / 17 |
| membership_monthly | number | A membership billed separately from the medication, in US dollars per month. | No separately billed membership was published with a readable monthly amount. It is not a published zero. | 1 / 17 |
| required_fees | list count | Every mandatory charge outside the medication rate, as label:amount/cadence, separated by semicolons. | none is written when no required fee was published. | 7 / 17 |
| commitment | string | The minimum term attached to the published rate, in the provider’s wording. | Blank means no commitment was stated in the source, not that none exists. | 4 / 17 |
| states | list count | How many states appear on a published service list for that record. | No readable list was published. Never nationwide, never 50 by default. | 4 / 17 |
| source_url | string | The provider page the row was read from. A third-party page is used only where no provider page exists. | Only where no resolvable provider page could be located. | 17 / 17 |
| check_date | ISO date | The date this row was last read from its source page, in ISO form. A corrected field carries the date of the later pass. | Never blank. | 17 / 17 |
The populated column is a coverage count, not a quality score: 9 of the 14 columns carry at least one blank, and every blank means that provider published nothing for that field on the pages read. Rows that cannot be tied to a provider page keep a blank and a note. A bad row is reported, never dropped, because dropping it would change the record without changing the log.
How to cite a row
Built from the records themselvesTwo worked examples, both generated from the live records rather than typed as sample text. If a price is corrected, the example changes with it. Replace the bracketed access date with the date you actually read the file.
A published charge — cite the row and its check date
Open Water RX LLC, “TRT price rows, 2026 edition” (TRT Buyer Guide). Row: Fountain TRT — charge as billed From $199/mo, published as a flat all-inclusive monthly fee; check date October 26, 2026. https://trtbuyerguide.com/datasets/trt-price-rows-2026 (accessed <date you read it>).
The charge and its wording are the provider’s own, so the row can be quoted as published. The qualifier travels with it — quote charge_as_billed, not the number alone, and attach this record’s check date rather than a blanket edition date.
A derived figure — say derived, and say what it excludes
Open Water RX LLC, “TRT price rows, 2026 edition” (TRT Buyer Guide). Row: Male Excel — known monthly subtotal $231 (derived from the cream rate plus the medical membership), check date October 26, 2026. https://trtbuyerguide.com/datasets/trt-price-rows-2026 (accessed <date you read it>).
$231 is not a figure the provider states. It is a subtotal of two published charges, and the all-in figure is withheld because a required fee has no published amount. Writing it up as the program’s price is the most common error in this edition.
What breaks a citation
- A charge without its billing interval is not a monthly price. Copy the interval with the number.
- An unpriced required fee is not free. It is a blank, and it withholds the total.
- A later-pass check date belongs to that record only. Do not stamp it on the whole edition.
- A blank cell is a finding about what the provider publishes, not a zero and not a cheap price.
The publisher is Open Water RX LLC, trading as TRT Buyer Guide. The dataset title, the row, the charge wording, the interval and the record’s own check date are the five parts a citable sentence needs.
Does the export match the visible rows?
17 of 17 rows matchEach row below is checked against the markdown export as it is generated: the charge written into the file is parsed back out and compared with the number printed in the row table, and the ISO check date must match character for character. Those are the two fields a citation rests on, so they are re-derived here rather than trusted. A mismatch is published, not hidden — a reader should not have to assume the download agrees with the page.
| Provider | Charge in the visible row | Charge in the export | Check date (ISO) — row / export | Result |
|---|---|---|---|---|
| Hims & Hershims-and-hers | 79 | 79 | 2026-10-262026-10-26 | Match |
| Hone Healthhone-health | 28 | 28 | 2026-10-262026-10-26 | Match |
| LifeMDlifemd | null | none recorded | 2026-10-232026-10-23 | Match |
| RexMDrexmd | 250 | 250 | 2026-10-262026-10-26 | Match |
| Marek Healthmarek-health | null | none recorded | 2026-10-262026-10-26 | Match |
| Maximus (Maximus Tribe)maximus | 199.99 | 199.99 | 2026-10-262026-10-26 | Match |
| Male Excelmale-excel | 132 | 132 | 2026-10-262026-10-26 | Match |
| Defy Medicaldefy-medical | null | none recorded | 2026-10-232026-10-23 | Match |
| Fountain TRTfountain-trt | 199 | 199 | 2026-10-262026-10-26 | Match |
| Peter MD (Peter Uncaged)peter-md | 139 | 139 | 2026-10-262026-10-26 | Match |
| Taurus Medstaurus-meds | 149 | 149 | 2026-10-262026-10-26 | Match |
| ReformHRTreformhrt | null | none recorded | 2026-10-232026-10-23 | Match |
| RegenX Healthregenx-health | null | none recorded | 2026-10-232026-10-23 | Match |
| Titan TRTtitan-trt | 159 | 159 | 2026-10-232026-10-23 | Match |
| Keepskeeps | null | none recorded | 2026-10-232026-10-23 | Match |
| Blokes (Joi + Blokes)blokes | 149 | 149 | 2026-10-262026-10-26 | Match |
| AlynMDalynmd | null | none recorded | 2026-10-262026-10-26 | Match |
This compares the generator output with the rows rendered above, for 17 records. The release-validation block on this page then diffs that same output against the file actually deployed, so the two checks together cover the whole chain from record to download. A blank charge is compared as a blank: it must not appear in the export as a figure.
Records checked October 26, 2026, each field dated to the pass that read it. Source dates travel with each row; nothing here is aggregated or smoothed. All 17 rows agree with the export text.
Release validation — generator command, parity and emitted-file diff
This block is for whoever prepares a release. It is not part of the reader's comparison path, and nothing here changes a figure.
The exact procedure
- Generator
- src/lib/machineDocs.ts → MACHINE_FILES (one entry per emitted file)
- Emit
- npx jiti src/lib/emitMachineDocs.ts regenerates and writes every file listed in MACHINE_FILES into public/ from this generator. Build-time wiring is NOT installed in this project, so this is a step you run explicitly before publishing. Where the command cannot run in the host, use the Copy generated text control on each file in the release-validation block and paste it into public/<path> verbatim.
- Validate
- Run the emit step, then npm run build, then /datasets → Release validation → Compare emitted files. Publishing is gated on that diff being empty.
Required before publishing
- Every parity check passes: 18 researched records / 17 researched eligible, the sponsored entry ranked first at its configured score without entering research coverage, charge parity, priced count, unknown-fee withhold, null-is-not-zero, ranks follow the configured positions, published snapshot, non-TRT not ranked, figures trace to data, snapshot equals generator, ranking matches the config, paid-placement disclosure, cost-study cohorts.
- Emitted-file diff is empty for all 8 generated files: /index.md, /buyerguide.md, /compare.md, /providers.md, /how-much-does-testosterone-therapy-cost.md, /providers/stahl-primary-care.md, /ai-info.md, /llms.txt. This is the pre-publish gate and it cannot be skipped.
- Claim specs pass for /how-we-compare.md, /criteria.md, /openapi.json, /.well-known/status.json, /.well-known/api-catalog.
- No stale string survives: $128 all-in, $231 all-in, ai-input=no, 18 ranked, content negotiation, a twelve-month Maximus rate, a Hone record with no medication rate, Price 45, Exemplary, a score described as a formula.
- Hone Health publishes a $28/mo medication rate and no all-in figure: Basic $25/mo or Plus $155/mo is unresolved for that rate, the $60 cream and troches stay separate, and $53 is never reported.
- One H1 per page; canonical path matches the route; no route added or removed.
Parity 16/16
The diff fetches each published file and compares it with the generator output, so a stale file is caught by content rather than by memory. A missing file reports as missing rather than as a match.
Generated text — copy fallback
Every entry below is the generator's current output for that path. When the emit command cannot run in the host, copy a file and paste it into the matching path in public/ so the published file matches the record. The diff above is the gate: publishing waits until it is empty.