ohash vs object-hash vs hash-wasm: Object Hashing in JavaScript (2026)
TL;DR
ohash is the UnJS super-fast object hashing library — deterministic hash of any JavaScript value, tiny, zero dependencies, used for cache keys and content addressing. object-hash is the mature object hashing library — SHA-1/SHA-256/MD5 of JavaScript objects, handles circular references, configurable key ordering. hash-wasm is a WebAssembly-based hashing library — blazing fast SHA-256, MD5, xxHash, Blake3 on raw data (strings/buffers), not specific to objects. In 2026: ohash for hashing JS objects (cache keys, ETags), object-hash for configurable object hashing, hash-wasm for raw data hashing at maximum speed.
Key Takeaways
- ohash: ~10M weekly downloads — UnJS, fast object hashing, deterministic, tiny
- object-hash: ~10M weekly downloads — configurable, multiple algorithms, circular reference support
- hash-wasm: ~3M weekly downloads — WASM-based, 30+ algorithms, raw data hashing
- ohash produces a quick hash for cache invalidation — not cryptographic
- object-hash produces SHA-1/SHA-256 — deterministic and verifiable
- hash-wasm is for raw data — hashing strings, buffers, files (not JS objects)
Common Use Cases
Why hash JavaScript objects?
✅ Cache keys — hash(requestParams) → unique cache key
✅ ETags — hash(responseBody) → HTTP ETag header
✅ Change detection — hash(config) changed? → reload
✅ Deduplication — hash(record) → check if already processed
✅ Content addressing — hash(data) → deterministic filename
Why hash raw data?
✅ File integrity — SHA-256(file) → verify downloads
✅ Password hashing — (use bcrypt/argon2 instead)
✅ Checksums — MD5(payload) → quick integrity check
✅ Bloom filters — xxHash(key) → fast probabilistic lookup
ohash
ohash — fast object hashing:
Basic usage
import { hash, objectHash, murmurHash, sha256 } from "ohash"
// hash() — quick hash of any value:
hash({ name: "react", version: "19.0.0" })
// → "aBcDeFgH" (short, deterministic hash string)
hash([1, 2, 3])
// → "xYzAbCdE"
hash("hello world")
// → "qRsTuVwX"
// Same input → same output (deterministic):
hash({ a: 1, b: 2 }) === hash({ b: 2, a: 1 })
// → true (key order doesn't matter)
Object hashing for cache keys
import { hash } from "ohash"
// API response caching:
function getCacheKey(endpoint: string, params: Record<string, unknown>) {
return hash({ endpoint, params })
}
const key = getCacheKey("/api/packages", { sort: "downloads", limit: 10 })
// → deterministic cache key
// ETag generation:
function generateETag(data: unknown) {
return `"${hash(data)}"`
}
app.get("/api/packages", (req, res) => {
const packages = getPackages()
const etag = generateETag(packages)
if (req.headers["if-none-match"] === etag) {
return res.status(304).end() // Not modified
}
res.setHeader("ETag", etag)
res.json(packages)
})
SHA-256 and Murmur hash
import { sha256, murmurHash } from "ohash"
// SHA-256 (cryptographic):
sha256("hello world")
// → "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
// Murmur hash (fast, non-cryptographic):
murmurHash("hello world")
// → 1586663183
// sha256 for content integrity:
const contentHash = sha256(JSON.stringify(config))
Diff and comparison
import { hash, diff } from "ohash"
// diff() — find differences between objects:
const changes = diff(
{ name: "react", version: "18.0.0", downloads: 5_000_000 },
{ name: "react", version: "19.0.0", downloads: 5_500_000 }
)
// → [
// { type: "changed", key: "version", oldValue: "18.0.0", newValue: "19.0.0" },
// { type: "changed", key: "downloads", oldValue: 5000000, newValue: 5500000 }
// ]
// isEqual — deep equality check:
import { isEqual } from "ohash"
isEqual({ a: 1 }, { a: 1 }) // → true
object-hash
object-hash — configurable object hashing:
Basic usage
import objectHash from "object-hash"
// SHA-1 by default:
objectHash({ name: "react", version: "19.0.0" })
// → "a1b2c3d4e5f6..." (40-char SHA-1 hex)
// SHA-256:
objectHash({ name: "react" }, { algorithm: "sha256" })
// → "abcdef123456..." (64-char SHA-256 hex)
// MD5:
objectHash({ name: "react" }, { algorithm: "md5" })
// → "a1b2c3d4..." (32-char MD5 hex)
Configuration options
import objectHash from "object-hash"
// Key ordering (default: sorted):
objectHash({ b: 2, a: 1 }) === objectHash({ a: 1, b: 2 })
// → true (keys sorted before hashing)
// Disable key sorting:
objectHash({ b: 2, a: 1 }, { unorderedObjects: false })
// → different from objectHash({ a: 1, b: 2 }, { unorderedObjects: false })
// Exclude specific keys:
objectHash({ name: "react", _internal: "skip" }, {
excludeKeys: (key) => key.startsWith("_"),
})
// Respect type differences:
objectHash({ value: 1 }, { respectType: true })
// Different from objectHash({ value: "1" })
Circular references
import objectHash from "object-hash"
// Handles circular references:
const obj: any = { name: "react" }
obj.self = obj // Circular!
objectHash(obj)
// → works fine, circular reference detected and handled
// ohash would throw on circular references by default
Specific value hashing
import objectHash from "object-hash"
// Hash specific types:
objectHash.sha1({ name: "react" }) // SHA-1
objectHash.MD5({ name: "react" }) // MD5
objectHash.keysMD5({ name: "react" }) // MD5 of keys only
// Write to stream (for large objects):
objectHash.writeToStream({ name: "react" }, { algorithm: "sha256" })
hash-wasm
hash-wasm — WASM-based hashing:
Fast hashing
import { sha256, md5, xxhash64, blake3 } from "hash-wasm"
// SHA-256:
const hash = await sha256("hello world")
// → "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
// MD5:
const md5Hash = await md5("hello world")
// → "5eb63bbbe01eeed093cb22bb8f5acdc3"
// xxHash64 (ultra-fast, non-cryptographic):
const xxHash = await xxhash64("hello world")
// → "d4a1185c118f2a57"
// Blake3 (modern, fast cryptographic):
const blake = await blake3("hello world")
// → "d74981efa70a0c880b8d8c1985d075dbcbf679b99a5f9914e5aaf96b831a9e24"
Buffer/file hashing
import { sha256, createSHA256 } from "hash-wasm"
import { readFile } from "node:fs/promises"
// Hash a file:
const buffer = await readFile("package.json")
const fileHash = await sha256(buffer)
// Streaming hash (for large files):
const hasher = await createSHA256()
hasher.init()
// Process in chunks:
for await (const chunk of readStream) {
hasher.update(chunk)
}
const result = hasher.digest("hex")
Performance advantage
Benchmark (hashing 1 MB of data):
hash-wasm (SHA-256, WASM): ~450 MB/s
Node.js crypto (SHA-256): ~400 MB/s
pure JS sha256: ~50 MB/s
hash-wasm (xxHash64, WASM): ~3,000 MB/s
Node.js crypto (N/A): —
pure JS xxhash: ~200 MB/s
hash-wasm is fastest in browsers (no native crypto).
In Node.js, built-in crypto is comparable for SHA-256.
xxHash/Blake3 via hash-wasm is much faster than any pure JS option.
Available algorithms
import {
md5, sha1, sha256, sha512, // Standard
xxhash32, xxhash64, xxhash128, // xxHash (non-crypto, ultra-fast)
blake2b, blake2s, blake3, // Blake (modern crypto)
crc32, adler32, // Checksums
argon2id, bcrypt, scrypt, // Password hashing
sha3_256, sha3_512, // SHA-3
keccak256, keccak512, // Keccak
} from "hash-wasm"
// 30+ algorithms available — all WASM-accelerated
Feature Comparison
| Feature | ohash | object-hash | hash-wasm |
|---|---|---|---|
| Hash JS objects | ✅ | ✅ | ❌ (raw data) |
| Hash raw data | ✅ (sha256) | ❌ | ✅ |
| Deterministic | ✅ | ✅ | ✅ |
| Key order independent | ✅ | ✅ (configurable) | N/A |
| Circular references | ❌ | ✅ | N/A |
| Algorithm choice | murmur, SHA-256 | SHA-1, SHA-256, MD5 | 30+ algorithms |
| WASM accelerated | ❌ | ❌ | ✅ |
| Streaming | ❌ | ✅ | ✅ |
| Object diff | ✅ | ❌ | ❌ |
| Browser support | ✅ | ✅ | ✅ |
| Dependencies | 0 | 0 | 0 |
| Weekly downloads | ~10M | ~10M | ~3M |
When to Use Each
Use ohash if:
- Need fast cache keys from JavaScript objects
- Building ETags or content-addressed storage
- In the UnJS ecosystem (Nuxt, Nitro, H3)
- Want object diff and equality utilities alongside hashing
Use object-hash if:
- Need configurable hashing (algorithm, key ordering, exclusions)
- Objects may have circular references
- Want SHA-1/SHA-256/MD5 hashes of JavaScript objects
- Need streaming hash support for large objects
Use hash-wasm if:
- Hashing raw data (strings, buffers, files) not JS objects
- Need maximum performance (WASM-accelerated)
- Want exotic algorithms (xxHash, Blake3, Keccak)
- Building file integrity checks, checksums, or content addressing
Methodology
Download data from npm registry (weekly average, February 2026). Feature comparison based on ohash v1.x, object-hash v3.x, and hash-wasm v4.x.