mrkeyoor.com_
Sat 08 Aug 20:58 UTC
npmUtilsupdated 08 Aug 2026

string-hash

string-hash turns a JavaScript string into a deterministic unsigned 32-bit integer. Its entire runtime is one CommonJS function based on a djb2-like loop, with no dependencies or configuration. That makes it useful for repeatable colors, buckets, and other non-security decisions where a compact number matters more than collision resistance. It is not encryption, a password hash, or a safe unique-ID generator.

Verdict

Keep it for low-stakes deterministic display choices or bucketing in an existing CommonJS app. Do not newly install it for security, identity, TypeScript ergonomics, or any workload where a collision causes damage.

API stability5/5The public API is one function that accepts a string and returns an unsigned 32-bit integer, and the README example still matches the published index.js exactly. Version 1.1.3 has been unchanged since 2017, so accidental API churn is unlikely, although that stability comes from a frozen project rather than ongoing compatibility work.
Docs3/5The short README accurately explains the djb2-like algorithm, states the exact numeric range, shows installation and CommonJS usage, and identifies the CC0 dedication. It does not document TypeScript, ESM, Unicode normalization, invalid inputs, collision expectations, browser support, or security boundaries, all of which users must infer from the tiny source file.
Maintenance1/5The latest npm release, 1.1.3, dates to 2017; GitHub reports the repository as archived and the last code push was in April 2020. An archived one-function package may continue working indefinitely, but users should expect no fixes, new module formats, declaration files, security response, or review of proposed changes.
Ecosystem3/5The package recorded 4,981,170 npm downloads in the measured week and has no runtime dependencies, so it remains deeply present in dependency trees. Its integration surface is deliberately tiny, however: there are no official adapters, plugins, TypeScript declarations, ESM entry point, or related toolkit beyond the single CommonJS export.

Use it if

  • You need the same non-negative 32-bit number every time a given string appears
  • You want deterministic UI colors, placeholder choices, or shard buckets without keeping a lookup table
  • You maintain CommonJS code and value a one-function package with no runtime dependencies
  • Collisions are acceptable and the hash never crosses a security boundary
Skip it if

Setup reality

Installation is only npm install string-hash, and there are no runtime dependencies, peer dependencies, native builds, environment variables, credentials, or config files. In CommonJS, require('string-hash') returns the function directly. The friction shows up in modern toolchains and in deciding whether the result is fit for purpose. The package has no bundled TypeScript declarations and no ESM export map, so strict TypeScript projects need an ambient declaration such as declare module 'string-hash' or a third-party types package, while native Node ESM relies on CommonJS interop. Inputs must be strings; passing an object does not serialize it, and the implementation reads length and charCodeAt directly. JavaScript strings are UTF-16, so normalization-equivalent Unicode text can hash differently unless you call normalize() first. The return value is a Number from 0 through 4294967295, not a hex string. Most importantly, collisions are an expected consequence of the 32-bit output. Never use the result as proof of equality, as a database uniqueness key, or anywhere an attacker benefits from choosing collisions. The package is archived and has not released since 2017, so there is no credible path for feature requests, ESM support, or bundled types; adopt it only if its frozen, tiny API is exactly what you want.

Patterns

Hash a string to an unsigned integerhash-string

const stringHash = require('string-hash');

const value = stringHash('Hello, world!');
console.log(value); // 343662184

The result is a JavaScript Number in the unsigned 32-bit range, not a cryptographic digest.

Assign a stable bucketassign-bucket

const stringHash = require('string-hash');

function bucketFor(userId, bucketCount) {
  if (!Number.isInteger(bucketCount) || bucketCount < 1) throw new RangeError('bucketCount');
  return stringHash(userId) % bucketCount;
}

console.log(bucketFor('user-42', 16));

Changing bucketCount reshuffles many values; use rendezvous or consistent hashing when stable rebalancing matters.

Make a repeatable rollout decisionpercentage-rollout

const stringHash = require('string-hash');

function isEnabled(flag, userId, percent) {
  const slot = stringHash(`${flag}:${userId}`) % 100;
  return slot < Math.max(0, Math.min(100, percent));
}

if (isEnabled('new-nav', 'user-42', 10)) showNewNav();

This is deterministic allocation, not tamper resistance; do not trust a client-computed result for authorization.

Choose a deterministic palette colorpick-color

const stringHash = require('string-hash');

const palette = ['#2563eb', '#7c3aed', '#db2777', '#ea580c'];
function colorFor(label) {
  return palette[stringHash(label) % palette.length];
}

console.log(colorFor('Ada Lovelace'));

Different labels can select the same color by design; this is a display mapping, not an identity check.

Select a repeatable placeholderpick-placeholder

const stringHash = require('string-hash');

const placeholders = ['/avatar-1.svg', '/avatar-2.svg', '/avatar-3.svg'];
const placeholderFor = (key) => placeholders[stringHash(key) % placeholders.length];

img.src = placeholderFor(account.email);

Hashing an email does not anonymize it; avoid exposing the numeric hash as if it protected personal data.

Normalize Unicode before hashingnormalize-unicode

const stringHash = require('string-hash');

function hashVisibleText(text) {
  return stringHash(text.normalize('NFC'));
}

console.log(hashVisibleText('café'));

Visually identical text can have different UTF-16 sequences; normalization makes canonical equivalents agree.

Hash a structured pair without ambiguous joinshash-composite-key

const stringHash = require('string-hash');

function hashPair(left, right) {
  return stringHash(JSON.stringify([left, right]));
}

console.log(hashPair('team:blue', 'member:7'));

JSON encoding avoids delimiter ambiguity, but the final 32-bit value can still collide.

Format the result as fixed-width hexadecimalformat-hex

const stringHash = require('string-hash');

const hex = stringHash('invoice-42').toString(16).padStart(8, '0');
console.log(hex);

Hex changes only the display format; it does not add entropy or make the algorithm cryptographic.

Use a hash as a quick check, then compare originalsverify-with-original

const stringHash = require('string-hash');

function probablySame(a, b) {
  if (stringHash(a) !== stringHash(b)) return false;
  return a === b;
}

console.log(probablySame('alpha', 'alpha'));

A matching hash is not proof of equality, so collision-sensitive code must compare the original values too.

Alternatives

PackageRegistryPick it when
imurmurhashnpmYou want incremental MurmurHash3 and may receive a value in chunks
hash-sumnpmYou need a short deterministic hash for JavaScript values and objects, not only strings
object-hashnpmYou need configurable hashing of objects with documented serialization behavior
crypto-jsnpmYou need standard cryptographic digest algorithms in browser-oriented JavaScript