SemVer Calculator

Compare and calculate semantic versions

Understanding SemVer Range Syntax
TL;DR

SemVer range syntax (^, ~, >=, ||) lets package managers resolve compatible versions. Understanding it prevents unexpected breaking changes.

What are SemVer Ranges?

While Semantic Versioning defines how to number releases, SemVer range syntax defines how to express which versions are acceptable as dependencies. Range syntax is the language that package managers like npm, Yarn, Cargo, and Composer use to determine which versions of a dependency are compatible with your project.

When you write "lodash": "^4.17.21" in your package.json, you are declaring a range: “any version of lodash that is greater than or equal to 4.17.21 and less than 5.0.0.” The package manager uses this range to select the best matching version from the registry, balancing between getting the latest bug fixes and avoiding breaking changes.

Understanding range syntax is essential for any developer who manages dependencies. Misconfigured ranges are a common source of “works on my machine” bugs, broken builds, and unexpected production issues.

Caret (^) vs Tilde (~)

The two most commonly used range operators are the caret (^) and tilde (~). They are the default in most package managers, and their behavior differs in a critical way.

Caret (^) — Compatible with Version

The caret allows changes that do not modify the left-most non-zero digit:

RangeEquivalentAllows
^1.2.3>=1.2.3 <2.0.0Minor and patch updates
^0.2.3>=0.2.3 <0.3.0Patch updates only
^0.0.3>=0.0.3 <0.0.4Nothing (exact match)

The caret is the default operator in npm. When you run npm install lodash, the version saved to package.json uses the caret prefix (e.g., ^4.17.21). For versions 1.0.0 and above, this is generally safe because SemVer guarantees backward compatibility within the same MAJOR version.

However, for 0.x versions, the caret becomes much stricter. ^0.2.3 only permits patch updates because the MINOR version is the left-most non-zero digit. This protects against the instability that SemVer allows during initial development.

Tilde (~) — Approximately Equivalent

The tilde allows only patch-level changes if a MINOR version is specified:

RangeEquivalentAllows
~1.2.3>=1.2.3 <1.3.0Patch updates only
~1.2>=1.2.0 <1.3.0Patch updates only
~1>=1.0.0 <2.0.0Minor and patch updates

The tilde is stricter than the caret for versions >= 1.0.0. While ^1.2.3 would accept 1.9.0, ~1.2.3 would not — it caps at the next MINOR version.

Caret vs Tilde Range Comparison A number line diagram showing that ^1.2.3 includes versions from 1.2.3 up to but not including 2.0.0, while ~1.2.3 includes only versions from 1.2.3 up to but not including 1.3.0. Range Comparison: ^1.2.3 vs ~1.2.3 1.0.0 1.2.3 1.3.0 1.5.0 1.9.0 2.0.0 ^1.2.3 = >=1.2.3 <2.0.0 ~1.2.3 ~1.2.3 = >=1.2.3 <1.3.0 Caret — allows minor + patch updates Tilde — allows patch updates only Dashed line = excluded boundary (upper bound is exclusive)

Comparison Operators

Beyond caret and tilde, SemVer range syntax supports explicit comparison operators that give you fine-grained control:

OperatorMeaningExampleResolves To
>=Greater than or equal>=1.2.31.2.3 and above (no upper bound)
>Greater than>1.2.3Above 1.2.3, not including it
<=Less than or equal<=2.0.02.0.0 and below
<Less than<2.0.0Below 2.0.0, not including it
=Exact match=1.2.3Only 1.2.3

You can combine operators to define precise ranges:

>=1.2.3 <2.0.0     # Same as ^1.2.3
>=1.0.0 <1.3.0     # 1.0.0 through 1.2.x

Hyphen Ranges

A hyphen between two versions defines an inclusive range:

1.2.3 - 2.3.4     # >=1.2.3 <=2.3.4
1.2 - 2.3.4       # >=1.2.0 <=2.3.4
1.2.3 - 2.3       # >=1.2.3 <2.4.0

When a partial version is used on the right side, missing components are treated as wildcards up to the next significant boundary. 1.2.3 - 2.3 means “up to but not including 2.4.0.”

X-Ranges and Wildcards

Any of the three version components can be replaced with x, X, or * to indicate “any value”:

RangeEquivalentDescription
*>=0.0.0Any version
1.x>=1.0.0 <2.0.0Any 1.x.x version
1.2.x>=1.2.0 <1.3.0Any 1.2.x version
"" (empty)>=0.0.0Same as *

X-ranges are useful for expressing intent clearly: 1.x says “I depend on the v1 API” without specifying which minor or patch version.

Combining Ranges with OR (||)

The double-pipe operator (||) combines multiple ranges. A version satisfies the combined range if it matches any of the sub-ranges:

^1.2.3 || ^2.0.0          # 1.x (>=1.2.3) OR 2.x
>=1.0.0 <1.5.0 || >=2.0.0 # 1.0-1.4.x OR 2.0+

This is useful when a library supports multiple major versions of a peer dependency. For example, a React component library might declare "react": "^17.0.0 || ^18.0.0" to support both React 17 and React 18.

SemVer Range Reference Table

SyntaxEquivalentnpm Default?Use Case
^1.2.3>=1.2.3 <2.0.0Yes (default)Accept minor + patch updates
~1.2.3>=1.2.3 <1.3.0NoAccept patch updates only
1.2.3=1.2.3NoExact version (pinned)
>=1.0.0 <2.0.0SameNoExplicit range
1.2.x>=1.2.0 <1.3.0NoWildcard patch
*>=0.0.0NoAny version
^1.2.3 || ^2.0.0UnionNoMultiple major versions

Common Use Cases

  • npm / Yarn dependencies: The package.json dependencies field uses SemVer ranges to declare acceptable dependency versions. The caret (^) is the default operator.
  • Peer dependencies: Libraries declare peer dependencies with ranges to support multiple major versions of frameworks (e.g., "react": "^17.0.0 || ^18.0.0").
  • CI/CD constraints: Build pipelines use ranges to specify tool versions, ensuring consistent builds while still receiving patch updates.
  • Lockfiles: package-lock.json and yarn.lock freeze the exact resolved versions, while package.json ranges define the acceptable version space.
  • Monorepo workspace protocols: Monorepo tools (Turborepo, Lerna, pnpm) use SemVer ranges to manage inter-package dependencies within the workspace.
  • Container images: Dockerfile FROM directives use version tags that follow SemVer conventions (e.g., node:18.17 for the latest 18.17.x patch).

Try These Examples

Compare Two Versions Valid

Compares version 1.4.2 with 2.0.0. The tool detects a MAJOR version difference, meaning breaking changes were introduced.

1.4.2
Caret Range — Satisfies Valid

Checks if version 1.9.0 satisfies the caret range ^1.2.3 (resolves to >=1.2.3 <2.0.0). Result: satisfies.

1.9.0
Tilde Range — Does NOT Satisfy Valid

Checks if version 1.3.0 satisfies the tilde range ~1.2.3 (resolves to >=1.2.3 <1.3.0). Result: does not satisfy, because tilde only allows patch updates.

1.3.0
Increment Minor Version Valid

Increments version 1.4.2 by a minor bump, producing 1.5.0. The patch number resets to 0.

1.4.2