Semantic Version (SemVer) Regex
Validate semantic version numbers with the official SemVer 2.0.0 pattern: major, minor and patch, an optional pre-release and optional build metadata.
One case per line; the m flag makes ^ and the end anchor work line by line.
Link optionspattern only
The address bar holds the pattern, flags and replacement, so Copy link shares them. Your test text stays out of it unless you include it (up to 2,000 characters), because it may be private. Nothing is sent to a server.
Matches
7matches
The first is “1.0.0”, at position 0.
- Groups
- 1, 2, 3, 4, 5
- Characters matched
- 94 of 142
What the pattern meansHover or tap a part to see it in the pattern and what it matched
How this works: Method, 4 sources, Checked against 1 worked example,
How this works
Method
Your pattern runs in your own browser’s JavaScript engine, in a background worker that is stopped after 1.5 seconds, so a pattern that backtracks catastrophically can’t freeze the page. The explanation comes from our own parser of the ECMAScript pattern grammar, checked against the engine; what each part matched is found by wrapping that part in one more group and running the pattern again. Conversions to other flavours only rewrite the syntax and list what their documentation says works differently.
Sources
How it’s tested
One worked example for this page is checked by automated tests before every release: given the inputs, the tool must show the expected answer.
Changes
- First published, with a library of 19 common patterns and their test cases.
Worked example
Take 1.0.0, the first case in the tester. Reading the pattern left to right, each part takes its share of the text:
^The start of the text (matches a position, no characters)(0|[1-9]\d*)Group 1, either of two alternatives: matches 1\.“.” matches .(0|[1-9]\d*)Group 2, either of two alternatives: matches 0\.“.” matches .(0|[1-9]\d*)Group 3, either of two alternatives: matches 0(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?A group (not captured), optional (zero or one time): (matches a position, no characters)(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?A group (not captured), optional (zero or one time): (matches a position, no characters)$The end of the text (matches a position, no characters)
How the SemVer regex works
This is the suggested regex with numbered capture groups published on semver.org, unchanged. Its first three groups read the major, minor and patch numbers with (0|[1-9]\d*): either a lone zero or a number that does not start with zero. That one rule rejects 01.0.0.
The optional pre-release starts with a hyphen and is captured as group 4. Each dot-separated identifier is either a number without leading zeros or \d*[a-zA-Z-][0-9a-zA-Z-]*, an alphanumeric identifier that contains at least one letter or hyphen. So 0.3.7 and alpha.1 pass, while 01 fails, because an all-digit identifier must follow the number rule.
Build metadata after a plus sign is group 5: one or more dot-separated runs of letters, digits and hyphens, where leading zeros are allowed. Because the groups are numbered, a match gives you each part directly, ready to compare.
- Semantic Versioning 2.0.0 says numeric identifiers must not include leading zeroes, which is why 01.0.0 and 1.0.0-01 fail. Source: Semantic Versioning 2.0.0.
- Build metadata must be ignored when determining version precedence, so 1.0.0+build.1 and 1.0.0+build.2 rank the same. Source: Semantic Versioning 2.0.0.
Test cases
Every case runs as an automated test of this page’s pattern, so the table can’t drift from what the pattern really does.
| Text | Result | Why |
|---|---|---|
| 1.0.0 | Passes | a plain release |
| 0.1.0 | Passes | major version zero, still in development |
| 1.0.0-alpha.1 | Passes | a pre-release with a numeric part |
| 1.0.0-0.3.7 | Passes | a pre-release made of numbers |
| 1.0.0-x.7.z.92 | Passes | mixed pre-release identifiers |
| 1.0.0+20130313144700 | Passes | build metadata only |
| 1.0.0-beta+exp.sha.5114f85 | Passes | pre-release and build metadata |
| 1.0 | Fails | the patch number is missing |
| 01.0.0 | Fails | a leading zero in the major version |
| v1.0.0 | Fails | a v prefix is a tag convention, not part of the version |
| 1.0.0-01 | Fails | a numeric pre-release identifier with a leading zero |
| 1.0.0- | Fails | an empty pre-release |
| 1.2.3.4 | Fails | a fourth number |
What it doesn’t check
- Many tools write tags as v1.2.3; strip the v before testing, since the specification does not include it.
- The regex validates one version, not a range: npm-style ranges such as ^1.2.0 or >=1.0.0 need a range parser.
- Comparing versions needs more than the regex: pre-release identifiers compare part by part, numbers numerically and text by ASCII order.
The same pattern in other languages
Converted automatically from the JavaScript version; the tester above always runs JavaScript.
| Flavour | Pattern | Notes |
|---|---|---|
| Python | (?a)^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*))*))?(?:\+([0-9a-zA-Z\-]+(?:\.[0-9a-zA-Z\-]+)*))?\Z | |
| PCRE | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*))*))?(?:\+([0-9a-zA-Z\-]+(?:\.[0-9a-zA-Z\-]+)*))?\z | |
| Go | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*))*))?(?:\+([0-9a-zA-Z\-]+(?:\.[0-9a-zA-Z\-]+)*))?$ | The pattern uses no lookarounds or backreferences, so it runs unchanged in Go’s RE2 engine. |
| Java | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*))*))?(?:\+([0-9a-zA-Z\-]+(?:\.[0-9a-zA-Z\-]+)*))?\z | |
| .NET | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*))*))?(?:\+([0-9a-zA-Z\-]+(?:\.[0-9a-zA-Z\-]+)*))?\z | In .NET, \d and \w match any Unicode digit or letter. Pass RegexOptions.ECMAScript, or write [0-9] and [A-Za-z0-9_], for JavaScript’s ASCII-only meaning. |
Sources
Frequently Asked Questions
Is there an official regex for semantic versioning?
Yes. The SemVer 2.0.0 specification suggests two: one with named groups and one with numbered groups for engines that lack named groups. This page uses the numbered version as published.
How do I allow a leading v, as in v2.1.0?
Add an optional v after the start anchor. Keep it out of the captured groups, so the major version is still group 1.
Can I compare two versions with this regex?
It extracts the parts, but you still compare them in code: major, then minor, then patch as numbers, and a version with a pre-release ranks below the same version without one.