This is an informational parsing and calculator tool. It does not endorse, recommend, source, or facilitate the purchase of any compound, and nothing here is medical advice.
coacheck reads a Certificate of Analysis (COA) - the lab report that ships with a research peptide vial - and does three things with it: extracts the fields (purity, batch number, test method, and so on) with regex, checks that the document contains what a COA is supposed to contain, and does the arithmetic to turn a labeled mass into a real deliverable mass and a reconstituted vial into a syringe draw. It doesn't judge whether to use anything; it does the math on what you give it.
Pure standard library, Python 3.9+, no runtime dependencies.
pipx install git+https://github.com/munzzyy/coacheckThere's no PyPI release yet, so install straight from the repo. Or clone it and run it in place, which needs nothing installed at all:
git clone https://github.com/munzzyy/coacheck
cd coacheck
python -m coacheck parse tests/fixtures/coa_clean.txt # run it directly, no install
pip install -e . # or install the `coacheck` command$ coacheck parse tests/fixtures/coa_clean.txt
Certificate of Analysis - parsed fields
Product name : Research Compound RC-118
HPLC purity : 99.1%
Net peptide content : 91.5%
Mass / quantity : 5 mg
Batch / lot : RC118-20260214-A
Test date : 2026-02-14
Test method : RP-HPLC-MS
Testing lab : Meridian Analytical Labs
Purity math
Labeled mass : 5 mg
Actual deliverable peptide: 4.534 mg (90.7% of labeled)
Shortfall : 0.466 mg (9.3%)
Red-flag checklist
[PASS] CC-PURITY Purity at or above the research-grade line
Stated purity is 99.1%.
[PASS] CC-MASS Mass/quantity present
Mass: 5 mg
[PASS] CC-BATCH Batch/lot number present
Batch/lot: RC118-20260214-A
[PASS] CC-LAB Testing laboratory named
Lab: Meridian Analytical Labs
[PASS] CC-METHOD Test method named
Method: RP-HPLC-MS
[PASS] CC-DATE Test date present
Test date: 2026-02-14
[PASS] CC-PURITY-METHOD Purity is backed by a named method
Method: RP-HPLC-MS
[PASS] CC-NET Net peptide content is within a plausible range
Net peptide content: 91.5%
0 fail, 0 warn, 8 pass (8 checks)
coacheck parse reads from a file, or from stdin if you leave the path off:
cat some-coa.txt | coacheck parseMost real COAs arrive as a PDF. Convert it first and pipe it in. -layout matters: it keeps
the column alignment, and a COA is nearly always a two-column table.
pdftotext -layout coa.pdf - | coacheck parsePass --json for machine-readable output:
coacheck parse tests/fixtures/coa_clean.txt --json--fail-on turns the checklist into an exit code so parse can gate a script. --fail-on fail exits 3 when any check FAILs, --fail-on warn exits 3 on a WARN or a FAIL. The default
is never, which always exits 0.
coacheck parse coa.txt --fail-on fail && echo "nothing obviously missing"parse can do the reconstitution math too, and it uses the deliverable mass it just computed
rather than the number on the label:
$ coacheck parse tests/fixtures/coa_clean.txt --recon-water 2 --dose 250
...
Purity math
Labeled mass : 5 mg
Actual deliverable peptide: 4.534 mg (90.7% of labeled)
Shortfall : 0.466 mg (9.3%)
Reconstitution (from the actual deliverable mass, not the labeled 5 mg)
Vial : 4.53383 mg
Bacteriostatic water: 2 mL
Concentration : 2266.91 mcg/mL
Dose : 250 mcg
Draw : 0.1103 mL (11.0 units on a U-100 insulin syringe)
Doses per vial : 18.14
...
The label implies 20.00 doses; the document's own purity figures say 18.14. Pass
--recon-basis labeled if you want the label number anyway. If the purity math couldn't run
there's no deliverable mass to use, and the block says so instead of quietly falling back.
$ coacheck recon --vial 5 --water 2 --dose 250
Reconstitution
Vial : 5 mg
Bacteriostatic water: 2 mL
Concentration : 2500 mcg/mL
Dose : 250 mcg
Draw : 0.1000 mL (10.0 units on a U-100 insulin syringe)
Doses per vial : 20.00
--dose is in mcg by default; pass --unit mg if you'd rather give it in mg. --json works
here too.
extension/ is a Manifest V3 browser extension (Firefox and Chrome, one codebase) that
does the same parsing and math without the command line: drag a box over a COA on any page,
it OCRs that region locally - bundled OCR engine, no network call, nothing leaves your
machine - and shows the parsed fields, purity math, a reconstitution calculator, and the
red-flag checklist right there on the page. See extension/README.md
for how to load it, the exact permissions it asks for and why, and how its JS port of this
engine is pinned to match the Python package exactly.
- Parses a COA text blob for product name, HPLC purity, net peptide content, mass/quantity,
batch/lot number, test date, test method, and testing lab, tolerating the label wording real
vendor documents vary ("Purity", "HPLC Purity", "Purity (HPLC)", colon, equals or dash
separators, case-insensitive). It also reads two-column table rows with nothing but
whitespace between label and value, which is what
pdftotext -layoutand the extension's OCR produce. On a table with a Specification column next to a Result column it reads the measured result, not the spec bound. Purity bounds written as words ("NLT 98.0%", "min. 98.0%") count the same as>=, and a mass in mcg, ug or g is normalized to mg. See docs/checks.md for the exact formulas. - Computes actual deliverable peptide mass from labeled mass, purity, and (if stated) net peptide content, plus the shortfall against the label in both mg and percent.
- Runs an 8-item red-flag checklist (
CC-PURITY,CC-MASS,CC-BATCH,CC-LAB,CC-METHOD,CC-DATE,CC-PURITY-METHOD,CC-NET), each a stable id with a pass/warn/fail status, documented in docs/checks.md. - Computes reconstitution math: concentration, mL to draw, units on a U-100 insulin syringe, and doses per vial, from a vial mass, diluent volume, and a dose you supply. Run off a parsed COA it uses the deliverable mass, not the labeled one.
- It does not verify that a COA is genuine. A fabricated document can fill in every field with invented numbers and pass every check here; this tool checks for missing or impossible data, not for forgery.
- It does not check a batch number, lab name, or test date against any outside registry. Every field is taken at face value from the text you give it.
- It does not recommend a dose, a product, or a source.
reconcomputes whatever--doseyou pass it; it has no opinion on what that number should be. - The
coacheckCLI is a regex parser over plain text. It doesn't do OCR and doesn't read PDFs or images (the browser extension does OCR, see above; for a PDF, pipepdftotext -layoutinto it). It can also miss a field worded in a way none of its label patterns cover - see CONTRIBUTING.md if you hit one. - No network calls, no telemetry, nothing phones home.
0- ran to completion. This is independent of the red-flag results: a report full of FAIL flags still exits0, because a failed check is information, not a tool error.1- invalid input: unparseable arguments torecon's math, or a COA text blob that's oversized or the wrong type.2- couldn't read the input at all (file not found) or a command-line usage error.3- only with--fail-on warnor--fail-on failonparse: the run succeeded and the checklist came back at or above the level you asked to fail on. Without the flag this code never happens.
What is left needs a decision, an account or a person this repo can't stand in for.
- A PyPI release. The release workflow is ready and only publishes from the tag that matches the package version, but the PyPI side still has to be set up and a release cut. Until then, install from git as shown above.
- A store listing for the extension. Today it loads only as a temporary add-on in Firefox or an unpacked one in Chrome. Whether it goes on addons.mozilla.org or the Chrome Web Store is still undecided.
- Whether the math should run on impossible values. A purity or net content over 100% fails the checklist, but the deliverable mass and the syringe draw are still computed from it, as docs/checks.md describes. A misread decimal point in OCR can produce exactly that kind of number. Two smaller calls go with it: whether CC-DATE should warn on a future date or one it can't read, and whether a second, different purity or mass in the same document should get its own warning.
- A pass with a real screen reader. The results panel has names, roles and keyboard handling, checked in tests and in headless Chromium, but nobody has used it with NVDA, VoiceOver or Orca yet.
- OCR on real COA screenshots. The extension's OCR is tested on clean synthetic text, and the public fixtures have to stay synthetic. Real vendor images have compression artifacts and odd layouts, so this needs people to try it on their own documents. If you do, please open an issue with the line it misread, retyped with made-up values.
See CONTRIBUTING.md. New label variants and new checks land with a test.
GPL-3.0-or-later. You can use, study, change and share it. If you distribute a copy or a modified version, it has to stay under the GPL and come with its source. Releases up to v0.1.0 were under MIT.
If coacheck saved you from a thin COA, sponsoring is what keeps it maintained.
