Sqids is a small open-source library that can produce short, unique, random-looking IDs from numbers.
The best way to think about it is like a decimal-to-hexadecimal converter, but with a few extra bells and whistles ✨
Link shortening, generating unique event IDs for logging, generating IDs for products/objects on a website (like YouTube does for videos), generating short IDs for text messages, confirmation codes in emails, etc.
Any data that's sensitive. Generated IDs are not hashes and could be decoded back into numbers. For example, they might not be a good choice for user IDs, because once decoded, they could reveal your app's user count.
Yes. Sqids can encode one or many non-negative numbers into a single ID. There is no limit to how many numbers you can encode, but there is a limit to how big of a number you can encode (depending on the implementation language).
This is useful for several reasons: you could encode a UNIX timestamp and create expiring IDs, or you could encode a database shard number along with a primary key and save up on extra database queries.
Yes, generated IDs are unique to the input and the alphabet.
Keep in mind though that the default alphabet contains both uppercase and lowercase letters, so default IDs are case-sensitive.
Sqids cannot encode negative numbers.
The minimum alphabet length is 3 characters.
The alphabet cannot contain any multibyte characters.
Sqids cannot generate IDs up to a certain length, only at least a certain length. The minimum length parameter range is between 0 and 255.
Sqids can attempt to regenerate IDs up to "alphabet length - 1" times.
The library accepts a custom alphabet from which it can generate IDs. Simply pre-shuffle the default alphabet that's provided.
Please keep in mind that given enough effort, somebody could reverse-engineer your shuffled alphabet, so this is by no means a technique to hide sensitive data.
Depends on your use case. A shorter alphabet will produce longer IDs, and a longer alphabet will produce shorter IDs. You can use the playground to test how your IDs might look.
Yes. Keep in mind that generated IDs are still strings and they might start with a "0".
No. Sqids does not support multibyte characters for the alphabet. That includes emojis as well as many other characters.
The library can extend IDs with junk characters to make them appear longer. This is useful so that it's not as obvious whether you're encoding a small number like 1 or a large number like 1,000,000.
Decoding is not affected.
Yes, the library accepts a minimum length parameter which guarantees that IDs will be at least that length.
Please note that there's no guarantee on how long your IDs will be — only that they will not be shorter than the length you specify.
Up to a point.
Setting max length is impossible because sooner or later your IDs will overflow given a big enough input. That's why only the minimum length parameter is supported, and the exact length or maximum length is not.
A blocklist can prevent certain words from appearing in your IDs. This is beneficial because generated IDs are meant to appear in public places, like the URL.
Sqids comes with the default blocklist that contains the most basic profanity and inappropriate words from several languages. You can of course extend that blocklist with your own words.
Blocklist word matching is case-insensitive.
Short words less than 3 characters long will not be blocked. Words 3 characters long have to match IDs exactly. Words 4 characters or longer will trigger a match if they're a substring of the ID.
If blocklist words contain numbers (leetspeak), they will only trigger a match if they're at the beginning or the end of the ID.
The default blocklist contains the most common profanity and inappropriate words from several languages. You can find the complete list here .
When the generated ID matches a word in the blocklist, the library attempts to regenerate it. It will do so "alpahbet length - 1" times.
If every single attempt fails to regenerate the ID, the encode function will fail and return an error. Handling that error is up to the user.
The best way to decrease the number of regeneration attempts is to have a longer alphabet, not set a minimum length, and provide a smaller blocklist. Providing an empty blocklist will disable the feature completely.
Decoding IDs will usually produce some kind of numeric output, but that doesn't necessarily mean that the ID is canonical. To check that the ID is valid, you can re-encode decoded numbers and check that the ID matches.
The reason this is not done automatically is that if the default blocklist changes in the future, we don't want to automatically invalidate the ID that has been generated in the past and might now be matching a new blocklist word.
We will be sure to update the CHANGELOG when and if the default blocklist changes.
You have to account for scenarios where a new word might be introduced to the default blocklist. In this case, re-encoding numbers might produce a different ID.
The best way to ensure your IDs stay consistent throughout future updates is to provide a custom blocklist, even if it is identical to the current default blocklist.
No, encoding different numbers will produce unique IDs.
However, because of the algorithm's design, decoding random IDs can sometimes produce the same numbers. The best way to check if the ID is canonical is to simply re-encode decoded numbers and check that the ID matches.
Hashids was the first version of this library that came out around 2013. It also produced short IDs but used a slightly different method.
Hashids handled a few things differently.
It did not support a custom blocklist, but instead relied on the most common English profanity words. It also used the "salt" parameter to shuffle the alphabet which made it a little confusing because the library has nothing to do with encryption. Additionally, it used too many reserved characters which resulted in producing longer IDs.
Therefore, we've decided to upgrade and rebrand. The algorithm has been simplified, a few features were added and the code repositories are all under one roof now .
The salt parameter was used to shuffle the alphabet, and it was never meant to be associated with security or safety. Both Hashids and Sqids work similarly to the way decimal to hexadecimal conversion works but with a few adjustments. There is no encryption of any kind, so to avoid confusion, that parameter has been removed completely.
No, Sqids expands on the functionality of Hashids and has different design goals & requirements; therefore, generated IDs are not compatible with Hashids.
Since there's no compatibility between Hashids and Sqids, it's impossible to simply replace Hashids with Sqids.
However, you can merge the two by differentiating which ID belongs to which library.
One of the ways to do that is by ID length - if you're switching to Sqids, you can provide a higher minimum length. Another way is to manually append/prepend a custom character to the newly generated IDs.
Finally, you could also attempt to decode an ID with Hashids to see if it's valid. If not - decode and re-encode with Sqids to see if that works.
Each language implementation on this website links to the original Hashids repository if it exists.
If you'd like to support the project, we'd appreciate starring our repos on Github for more visibility.
If you're a developer and see no implementation of Sqids for a particular language, please help us convert the library. The same goes for a programming language that is not listed.
If you see a bug in the spec or any of the implementations, please create an issue or a pull request with a suggested fix in the appropriate repository.
Finally, if you have some experience with Hashids/Sqids, please help guide our community and answer questions.
We could always use help on the following. Please reach out to 4kimov if you'd like to port the library:
ActionScript , Bash , C , Clojure , ColdFusion , C++11 , Crystal , D , Dart , Elixir , Elm , Erlang , Haxe , Io , Java , Kotlin , Lua , Nim , Objective-C , OCaml , Perl , PLpgSQL , PostgreSQL , R , Raku , Smalltalk , Swift , T-SQL , Tcl , VBA