hashids.net: reversible IDs, a minimum length but no maximum, and a note pointing elsewhere
GitHub describes it as A small .NET package to generate YouTube-like hashes from one or many numbers. Use hashids when you do not want to expose your database ids to the user.. The repository metadata lists C# as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- A small .NET package that turns integers into short YouTube-like strings and back again, with a salt, a custom alphabet and a minimum length. It is not a hash, it cannot be given a maximum length, and the author's own README suggests a different library. The last commit on the default branch is dated 25 October 2023.
- Who is it for?
- hashids.net suits a .NET developer who needs short, non-sequential, reversible identifiers for internal numbers, who accepts that anyone holding the salt can decode them, and who needs the specific conveniences this API already has: long overloads, single-value decode helpers and hex conversion.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Probably not. The repository last received commits 36 months ago, on October 25, 2023.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Star history
- ullmark/hashids.net3,353 ★ · -1
| Repository | 2026-08-13 | 2026-10-22 |
|---|---|---|
| ullmark/hashids.net | 3.4k | 3.4k |
-1 Stars in the last 70 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The README opens by pointing you at a different library
The most useful paragraph in the README is the note at the top, and it is an instruction to look elsewhere. It says you might want to use sqids-dotnet instead, because the original author of the hashids algorithm has rebranded and created a new algorithm called sqids, with the reasoning explained on the hashids organisation page and a .NET implementation of the new algorithm hosted on the sqids site. The same paragraph states the status of this package plainly: it has more or less been considered feature complete since its creation in 2012, it will remain available, and it will accept pull requests for bug fixes, but no new features will be added. So the choice is between a maintained successor and a frozen implementation, and the frozen one is the subject of this page.
Reversible by design, which rules out security use
The notes section removes the most common misunderstanding in one line: this is not a true cryptographic hash, since it is reversible. The Randomness section then sets expectations about what the algorithm does try to do, which is to make hashes unguessable and unpredictable, and to be non-sequential for incremental input so consecutive database ids do not produce consecutive-looking strings. It also says what the package is not meant for, namely security purposes or compression. Those two sentences together describe the whole threat model: obfuscation for humans reading a URL, not protection against someone who wants the number back. The examples make the point concrete, since encoding the same number twice with the same salt always produces the same string, and encoding 1 through 5 in sequence produces five unrelated-looking results.
Zero and positive integers, a minimum length, and no maximum at all
The constraints are listed rather than enforced silently, and three of them will shape your design. Only zero and positive integers are supported, so a negative number is not encoded at all. Only a minimum hash length can be specified, and there is no way to fit arbitrary numbers within a maximum hash length, which means a small id and a large id can come out at very different sizes. The alphabet must contain at least sixteen unique characters and is case sensitive, separators are the characters used to encode several numbers in one hash and must themselves be in the alphabet, and the salt must be smaller than the available alphabet, limited to the length of the alphabet minus the separators minus one.
Decode returns an array, so four helpers exist for the single case
Encoding is one call, decoding is another, and the asymmetry is where most of the API surface sits. Because Decode and DecodeLong hand back an array of numbers even when the hash held exactly one value, the package offers a helper for each shape: DecodeSingle and DecodeSingleLong return a value directly, and TryDecodeSingle and TryDecodeSingleLong report success through a boolean. A failure to decode is reported as a NoResultException, which you can catch to see what went wrong. The behaviour that deserves the most attention is the salt mismatch: decoding with a different salt does not throw, it returns an empty array, so a misconfigured salt looks like a hash that simply encoded nothing.
Salt, alphabet and minimum length are all part of a hash's identity
The constructor takes the salt first and the other two settings after it, and each one changes the output for identical input. Encoding the number 1 with the default settings and a minimum length of eight produces a padded eight character string, and the same number encoded with a custom alphabet produces a completely different string again:
var hashids = new Hashids("this is my salt", 8);
var hash = hashids.Encode(1);var hashids = new Hashids("this is my salt", 0, "abcdefghijkABCDEFGHIJK12345")
var hash = hashids.Encode(1, 2, 3, 4, 5)The README gives the results for both, gB0NV05e and Ec4iEHeF3, and because the alphabet and the salt are baked into every hash, none of those strings survives a change to either setting.
Hex goes in and comes back out, and the README doubles as test vectors
Two extra conversions sit on top of the numeric ones. EncodeHex turns a hexadecimal string into a hash, so DEADBEEF becomes kRNrpKlJ, and DecodeHex turns it back. The rest of the examples are less about features and more about demonstrating the unpredictability claim: four identical numbers encoded together produce a string with no visible repetition, ten consecutive numbers produce a long mixed string, and a table shows what each successive single number encodes to, none of which resembles the previous one. Taken together those examples are the specification a test suite can be written against, since every one of them has a documented expected output for a documented salt.
A solution file, three shell scripts, and no GitHub releases since 2023
The repository is a small Visual Studio solution with a source directory, a test directory, an editor configuration file and three shell scripts named build, pack and benchmark, so the packaging and performance work is scripted rather than done by hand in a CI configuration. Distribution happens through the package manager rather than through releases: installation is a single Install-Package command for hashids.net, and the repository publishes no GitHub releases at all. The version history lives in a changelog section inside the README instead, whose most recent entry is 1.7.0. The last commit on the default branch is dated 25 October 2023, which is consistent with the stated policy of accepting bug fixes without adding features, and the licence is MIT.
Editorial conclusion
hashids.net suits a .NET developer who needs short, non-sequential, reversible identifiers for internal numbers, who accepts that anyone holding the salt can decode them, and who needs the specific conveniences this API already has: long overloads, single-value decode helpers and hex conversion. It does not suit a new project without reading the README's opening note, because the original author rebranded the algorithm as sqids and publishes a .NET implementation of that instead, while this library has been described as feature complete since 2012. Three things to check before you adopt it: whether the obfuscation is enough for your threat model, since the README says plainly it is not built or tested for security; whether your identifiers have a length you need to respect, because only a minimum can be set and there is no way to force large numbers into a maximum; and whether the salt, alphabet and minimum length you choose will still be the ones in production later, because changing any of them changes every hash already in circulation.
Frequently asked questions
What is hashID?
hashids converts numbers into short YouTube-like strings and back again: the number 347 encodes to yr8, and the array 27, 986 encodes to 3kTMd. It supports a single value or several, int and long, with a salt, a custom alphabet and a minimum hash length. It is reversible, so it is obfuscation rather than a cryptographic hash.
Should I use hashids.net or sqids-dotnet?
The README of hashids.net suggests sqids-dotnet, because the original author of the algorithm rebranded and created sqids, with a .NET implementation on the sqids site. hashids.net itself has been considered feature complete since 2012 and will accept pull requests for bug fixes but no new features.
How do I install and start using hashids.net?
Install the package with Install-Package hashids.net, import the HashidsNet namespace, and construct with a salt, for example new Hashids("this is my salt"). Encode(12345) then returns NkK9, and Decode of that string returns an array holding 12345. Values stored as Int64 use EncodeLong and DecodeLong.
What are the constraints when using hashids.net?
Only zero and positive integers are encoded, so negative numbers are not supported. Only a minimum hash length can be set, never a maximum. The alphabet needs at least sixteen unique characters and is case sensitive, separators must be part of the alphabet, and the salt must be smaller than the alphabet, limited to the alphabet length minus separators minus one.
How do I decode a single hash with hashids.net?
Decode and DecodeLong return an array, so use DecodeSingle or DecodeSingleLong for a direct value, or TryDecodeSingle and TryDecodeSingleLong for a boolean result. A failed decode raises NoResultException, and decoding with a different salt than the one used to encode returns an empty array rather than an error.
Is hashids.net still being worked on?
The last commit on the default branch is dated 25 October 2023, and the repository publishes no GitHub releases, with the version history kept in a changelog section in the README whose latest entry is 1.7.0. The stated policy is that the library remains available and takes bug fixes but no new features.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ullmark-hashids-net)Star history chart for your README
[](https://hysenlabs.com/projects/ullmark-hashids-net)