How to Validate Semantic Versions Against the Semver Spec
Validate semantic versions in a pasted list against the semver spec: catch 1.2, 1.2.x, and leading zeros, then export a clean CSV or JSON report.
How to Validate Semantic Versions Against the Semver Spec
A version string looks trivial until you have two hundred of them in a release matrix and one of them is 1.2. Then your build script picks the wrong artifact, or your changelog generator skips a row, or a dependency pin resolves to something nobody intended. Semantic versioning has a precise grammar, and a list of versions is only as trustworthy as its weakest line.
The Semantic Version List Validator checks every line in a pasted block or an uploaded text file against that grammar, marks each one pass or fail, and writes the reason next to every reject. Everything runs in your browser, so a list of internal release tags never leaves the tab.
What strict semver actually requires
The semver spec is stricter than most people assume. A valid version has three numeric parts in the form MAJOR.MINOR.PATCH — all three present, all three numeric, none with a leading zero. After the patch number you may attach an optional -prerelease identifier (like -alpha.1 or -rc.2) and an optional +build metadata tag (like +20260613 or +sha.5114f85), in that order.
That single rule rejects a surprising amount of real-world input:
1.2is missing the patch number, so it fails. Two-part versions are common in marketing copy and in older tooling, but they are not semver.1.2.xhas a non-numeric patch part. Thexplaceholder belongs to range syntax, not to a concrete version, so it fails the grammar.01.2.3has a leading zero in the major part. Semver forbids leading zeros in any numeric identifier, so this is rejected even though it "looks like" a number.1.0.0-has an empty pre-release identifier — a dangling hyphen with nothing after it — and fails.
What this validator accepts and rejects
It is worth being exact about the rule this tool enforces, because semver tooling varies in how literally it reads the spec.
This validator requires all three numeric parts and rejects leading zeros in any of them. The pre-release and build sections are both optional, and when present they must be non-empty sequences of letters, digits, dots, and hyphens. So 1.0.0, 2.4.10-alpha.beta, 1.0.0-rc.1+build.7, and 3.0.0+20260613 all pass.
One deliberate point of leniency: a leading v is tolerated. v1.2.3 passes here, because v-prefixed tags are how Git, GitHub releases, and most CI pipelines actually store versions in the wild. The strict semver spec treats the v as not part of the version itself, so if you need spec-pure strings you should strip the prefix downstream — but for cleaning a list of release tags, accepting v1.2.3 is the practical choice. Anything that fails the three-part numeric core, carries a leading zero, or has an empty -/+ section is flagged with the reason Semantic version should be MAJOR.MINOR.PATCH with optional prerelease/build metadata.
A worked example
Here is a messy list pasted straight from a spreadsheet column and a chat thread:
1.0.0
v2.4.10
1.2
1.2.x
01.2.3
3.0.0-rc.1+build.42
1.0.0-
2.4.10
Run it through the validator with Keep invalid rows for review turned on, and the CSV output reads:
value,normalized,line,valid,reason
1.0.0,1.0.0,1,true,OK
v2.4.10,v2.4.10,2,true,OK
1.2,,3,false,Semantic version should be MAJOR.MINOR.PATCH with optional prerelease/build metadata.
1.2.x,,4,false,Semantic version should be MAJOR.MINOR.PATCH with optional prerelease/build metadata.
01.2.3,,5,false,Semantic version should be MAJOR.MINOR.PATCH with optional prerelease/build metadata.
3.0.0-rc.1+build.42,3.0.0-rc.1+build.42,6,true,OK
1.0.0-,,7,false,Semantic version should be MAJOR.MINOR.PATCH with optional prerelease/build metadata.
2.4.10,2.4.10,8,true,OK
Four passes, four flagged rejects, each with the line number so you can jump back to the source. Notice that v2.4.10 passes while 01.2.3 fails — the leniency is the leading v, not leading zeros. If you instead turn on Remove duplicates, the 2.4.10 on line 8 collapses against the v2.4.10 form only if they are byte-identical; the v prefix makes them distinct strings, which is exactly what you want when one row is a Git tag and the other is a bare version.
Why I keep the invalid rows
The first time I cleaned a version list for a release audit, I exported only the valid rows and felt productive. Then a reviewer asked which entries got dropped and why, and I had nothing — I had thrown away the evidence. Now I always keep the invalid rows with their reasons and download the CSV with line numbers. When someone questions a decision three weeks later, I open the artifact and point at the row: 1.2 failed because it had no patch number, line 14. The validation report is not just a filter, it is a paper trail. That habit turned a recurring argument into a thirty-second lookup.
From clean list to the format you actually need
Validation is the first step; the tool also reshapes the surviving list. You can deduplicate, sort the normalized output, and then switch the export between plain lines, CSV, JSON, Markdown, a SQL IN (...) clause, and a TypeScript union type. That last one is handy when you want a literal type like type SupportedVersion = '1.0.0' | '2.4.10' | '3.0.0-rc.1' without hand-typing every quote and comma.
If your job is narrower than full validation, the focused tools cover each step on its own: pull versions out of noisy text with the semantic version extractor, collapse duplicates with the semantic version deduplicator, canonicalize spacing and casing with the semantic version normalizer, or reshape an already-clean list with the semantic version list converter. Working with other structured strings? The ISO date extractor applies the same pass/fail-with-reason approach to dates.
A few practical cautions
A version passing the grammar tells you the string is well-formed, not that the release exists, builds, or is safe to deploy. Format validity and reality are different claims. Text copied from web pages or spreadsheets also tends to carry hidden whitespace and zero-width characters, so normalize before you deduplicate, otherwise two visually identical versions stay split. And when an audit trail matters, download the CSV or Markdown with line numbers rather than copying only the final list — the reasons column is the part future-you will want.
Semantic versions are small, but a list of them is a contract between your tooling and your releases. Checking that contract line by line, in the browser, with a reason beside every reject, is the cheapest way to keep a broken 1.2 from quietly breaking everything downstream.
Made by Toolora · Updated 2026-06-13