Compare Semantic Version Numbers with SemVer Precedence
Find out which of two versions really comes first: 1.0.0-alpha.1 is lower than 1.0.0-alpha.beta, because a numeric label always ranks below a word, and 2.10.0 correctly beats 2.9.0. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- First version
- 1.0.0-alpha.1
- Second version
- 1.0.0-alpha.beta
- Comparison
- less
- Precedence
- -1
- Greater version
- 1.0.0-alpha.beta
Compare two semantic version numbers without relying on lexical sorting, floating-point conversion, or package-manager-specific shortcuts. This capability validates both inputs against Semantic Versioning 2.0.0 and then applies the official precedence rules to the major, minor, patch, and prerelease components. It reports whether the first version is less than, greater than, or equal in precedence to the second, while correctly ignoring build metadata. Invalid or incomplete version strings produce a clear input error instead of a misleading ordering result.
Compare versions with the rules software releases actually use
Ordinary string comparison gives the wrong answer for many release numbers. For example, a lexical sort can place 2.10.0 before 2.9.0 because it compares the character 1 with 9, while numeric conversion loses the separate meaning of major, minor, and patch positions. This semantic version comparator parses each required position independently and compares them from left to right.
It also refuses loose forms such as a missing patch component, a leading v, or a numeric core identifier with a leading zero. That strict validation is valuable in deployment scripts, package registries, update services, and CI checks because malformed data cannot silently pass through as though it were a legitimate release. Submit the first and second versions exactly as published.
The result includes a signed precedence value: minus one means the first is lower, zero means equal precedence, and one means the first is higher. A descriptive comparison field makes the same answer convenient for interfaces and workflow conditions.
Understand prerelease ordering and build metadata
Prerelease identifiers are where simplistic comparators most often fail. A release with a prerelease suffix has lower precedence than the same major, minor, and patch version without that suffix, so 1.0.0-rc.1 is lower than 1.0.0. When both versions are prereleases, identifiers are compared in sequence.
Numeric identifiers compare by numeric magnitude, nonnumeric identifiers compare using ASCII lexical order, and a numeric identifier always has lower precedence than a nonnumeric identifier. If every shared identifier matches, the version with more identifiers has higher precedence. These rules reproduce the standard progression from alpha through beta and release candidates without assuming that particular words have special meanings.
Build metadata after a plus sign is validated but deliberately excluded from precedence. Consequently, 1.0.0+linux and 1.0.0+windows compare as equal even though their strings differ.
Use strict comparison safely in automation
A deterministic comparison result can become a small, dependable decision point in larger systems. A release pipeline can require the proposed version to be greater than the deployed one. An updater can decide whether a downloaded manifest represents an upgrade, downgrade, or equivalent build.
A test suite can cover the canonical prerelease chain and reject invalid tags before artifacts are published. The implementation performs no network requests, reads no clock, and uses no random values, so the same inputs always produce the same output. It compares numeric identifiers as digit strings rather than converting them to JavaScript numbers, which preserves correct ordering even when a valid identifier is far larger than the safe integer range.
Inputs are limited to a practical maximum length to keep processing bounded.
What you can do with it
Protect a release pipeline
Confirm that a proposed package version has higher precedence than the currently deployed version before publishing.
Evaluate update manifests
Determine whether a remote release represents an upgrade, downgrade, or equal-precedence build without metadata affecting the decision.
Validate prerelease sequences
Test alpha, beta, release-candidate, and final version ordering while rejecting malformed Semantic Versioning strings.
FAQ
What does the comparison value mean?
A precedence of -1 means the first version is lower, 0 means both have equal precedence, and 1 means the first version is higher.
Does build metadata affect the result?
No. Build metadata is validated, but Semantic Versioning excludes it from precedence comparisons.
Is a prerelease lower than the corresponding final release?
Yes. For identical major, minor, and patch numbers, a version with prerelease identifiers has lower precedence than the final version.
Are leading zeros accepted?
Numeric major, minor, patch, and numeric prerelease identifiers cannot contain leading zeros, except for the single digit zero.
Can I include a leading v or omit the patch number?
No. Inputs must be strict Semantic Versioning 2.0.0 strings such as 1.2.3 or 1.2.3-rc.1.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev2/semver-compare \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"first_version":"2.1.0-rc.1","second_version":"2.1.0"}'const res = await fetch("https://api.kit.forhosting.com/dev2/semver-compare", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"first_version": "2.1.0-rc.1",
"second_version": "2.1.0"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev2/semver-compare",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"first_version": "2.1.0-rc.1",
"second_version": "2.1.0"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev2/semver-compare", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"first_version":"2.1.0-rc.1","second_version":"2.1.0"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"first_version":"2.1.0-rc.1","second_version":"2.1.0"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev2/semver-compare", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"first_version": "2.1.0-rc.1",
"second_version": "2.1.0"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev2.semver_compare",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_chars_per_version | 1024 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Understand prerelease ordering and build metadata
When precedence is equal, greater_version is null because neither input outranks the other. This distinction prevents metadata labels from accidentally controlling upgrades.
Use strict comparison safely in automation
Treat an invalid_input response as a data-quality failure that should be corrected, not as one side being lower.
Technical questions
What does it cost?
The API price is $0.002 per comparison. The browser runner is available for interactive checks.