Semver Calculator - Parse, Compare & Test Semantic Versions Online
Parse, compare, sort, and test semantic versioning strings against npm-style ranges. Supports caret, tilde, wildcards, and OR ranges — 100% client-side, no data sent to server.
Frequently Asked Questions
What is Semantic Versioning (SemVer)?
Semantic Versioning is a versioning standard that uses a three-part number format: MAJOR.MINOR.PATCH. The MAJOR version increments for backward-incompatible changes, MINOR for backward-compatible new features, and PATCH for backward-compatible bug fixes. It is defined by the SemVer 2.0.0 specification and is used across virtually all modern package ecosystems including npm, PyPI, Cargo, and Go modules.
How do I use this semver calculator tool?
Choose one of the four tabs based on your need: (1) Compare — enter two versions to see which is greater, (2) Range Check — enter a version and an npm-style range to test if the version satisfies it, (3) Sort — paste multiple versions to sort them by precedence, (4) Bump — enter a version to see the next major, minor, patch, and pre-release versions. All results update in real-time as you type.
Is my version data safe? Does it get sent to a server?
All parsing, comparison, and range checking is performed 100% client-side in your browser using JavaScript. No data is transmitted to any server. Unlike tools that query the npm registry, this tool works entirely offline, making it safe for internal or proprietary version strings.
What is the difference between caret (^) and tilde (~) ranges?
The caret (^) range allows changes that do not modify the left-most non-zero digit: ^1.2.3 means >=1.2.3 <2.0.0. The tilde (~) range allows only patch-level changes: ~1.2.3 means >=1.2.3 <1.3.0. For 0.x versions, caret behaves more restrictively: ^0.2.3 means >=0.2.3 <0.3.0 (same as tilde in this case).
How does SemVer handle pre-release versions?
Pre-release versions are appended with a hyphen (e.g., 1.0.0-alpha, 1.0.0-beta.1). They have lower precedence than the associated normal version, so 1.0.0-alpha < 1.0.0. Pre-release identifiers are compared left-to-right: numeric identifiers compare as integers, alphanumeric identifiers compare lexically, and numeric identifiers always have lower precedence than alphanumeric ones.
What is build metadata and does it affect version comparison?
Build metadata is appended with a plus sign (e.g., 1.0.0+build.123). Per the SemVer 2.0.0 specification, build metadata MUST be ignored when determining version precedence. This means 1.0.0+build.1 and 1.0.0+build.999 are considered equal in precedence.
Can I test a range against multiple versions at once?
Yes. In the Range Check tab, enable Batch Mode to enter multiple versions (one per line). The tool will test each version against your range expression and show color-coded results, along with the minimum and maximum satisfying versions from your list.
Code Examples
// Semantic Versioning Parser & Comparator
function parseSemVer(version) {
const match = version.trim().match(
/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([\w.]+))?(?:\+([\w.]+))?$/
);
if (!match) return null;
return {
major: parseInt(match[1], 10),
minor: parseInt(match[2], 10),
patch: parseInt(match[3], 10),
prerelease: match[4]
? match[4].split('.').map(id => /^\d+$/.test(id) ? parseInt(id, 10) : id)
: [],
build: match[5] ? match[5].split('.') : [],
};
}
function compareSemVer(a, b) {
for (const key of ['major', 'minor', 'patch']) {
if (a[key] > b[key]) return 1;
if (a[key] < b[key]) return -1;
}
if (a.prerelease.length > 0 && b.prerelease.length === 0) return -1;
if (a.prerelease.length === 0 && b.prerelease.length > 0) return 1;
const len = Math.max(a.prerelease.length, b.prerelease.length);
for (let i = 0; i < len; i++) {
if (i >= a.prerelease.length) return -1;
if (i >= b.prerelease.length) return 1;
const ai = a.prerelease[i], bi = b.prerelease[i];
if (ai === bi) continue;
if (typeof ai === 'number' && typeof bi === 'number') return ai < bi ? -1 : 1;
if (typeof ai === 'number') return -1;
if (typeof bi === 'number') return 1;
return ai < bi ? -1 : 1;
}
return 0;
}
function sortVersions(versions, ascending = true) {
return versions
.map(v => ({ raw: v, parsed: parseSemVer(v) }))
.filter(v => v.parsed !== null)
.sort((a, b) => compareSemVer(a.parsed, b.parsed) * (ascending ? 1 : -1))
.map(v => v.raw);
}
// Example
const versions = ['2.0.0', '1.0.0-alpha', '1.0.0', '1.2.3', '0.9.0'];
console.log('Sorted:', sortVersions(versions));
// ['0.9.0', '1.0.0-alpha', '1.0.0', '1.2.3', '2.0.0']