hide-my-json
v0.1.1
Published
Obfuscate JSON payloads via gzip + XOR + Base62 encoding
Maintainers
Readme
hide-my-json
Obfuscate JSON payloads via Base62 encoding with optional gzip compression and XOR encryption.
Why?
When your web app exchanges JSON with your server, the data is easily readable in browser DevTools — anyone can inspect network requests and see exactly what you're sending and receiving. hide-my-json makes that data unreadable to casual observers by encoding it into a compact Base62 string, with optional compression and encryption.
This is not a substitute for proper encryption (use HTTPS + TLS for that). It's an obfuscation layer designed to discourage casual inspection and make reverse-engineering your API payloads significantly harder.
Use it when you want to:
- Hide JSON structure from browser DevTools / network inspectors
- Make API payloads opaque to curious users
- Add a lightweight obfuscation layer on top of HTTPS
- Transfer compact, encoded data between client and server
Installation
npm install hide-my-jsonQuick Start
import { HideMyJson } from "hide-my-json";
// Encode — gzip + Base62 (default)
const { payload } = await HideMyJson.encode({ user: "john", role: "admin" });
// → "G1ZwXNZN6ZjIZibSGwPA0fOJUw5BWadzgsp1Y53ktDlSMfbVM8cJO3N49xkWRoYg8Iq"
// Decode
const { data } = await HideMyJson.decode(payload);
// → { user: "john", role: "admin" }Usage
Basic Obfuscation (gzip + Base62)
By default, data is gzip-compressed and then Base62-encoded:
const { payload } = await HideMyJson.encode({
user: "john",
role: "admin",
permissions: ["read", "write"],
});
console.log(payload);
// → "3LVZjVORY66shXSyroEZjmJoOLTSYLNurmyelLR95UfXGNVVXxTwgOxmSRBRPvheTDKn3wrGTKfBJgy8cDaNnBWYv7mKFwMRC3xDQHzge"With XOR Encryption
Pass an xorKey to add XOR encryption on top of gzip:
const opts = { xorKey: "my-secret-key" };
const { payload } = await HideMyJson.encode({ token: "abc123" }, opts);
// → "Z8bmC2yph49yuCWTbNGDzguj9o4gdAJGiakBhoJquWGYHw4coVB"
const { data } = await HideMyJson.decode(payload, opts);
// → { token: "abc123" }Both sides must use the same options. If you encode with
xorKey, you must decode with the samexorKey.
Without Gzip (Base62 only)
Disable gzip for small payloads where compression overhead isn't worth it:
const opts = { useGzip: false };
const { payload } = await HideMyJson.encode({ id: 1 }, opts);
// → "AZRNdCjY0Wz"
const { data } = await HideMyJson.decode(payload, opts);
// → { id: 1 }Gzip in Action
Gzip really shines on repetitive data. Here's a 930-byte JSON compressed down to a 195-character payload — 84% smaller:
const logs = {
logs: [
{
timestamp: "2024-01-01T00:00:00Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:01Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:02Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:03Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:04Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:05Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:06Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:07Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:08Z",
level: "info",
message: "User logged in successfully",
},
{
timestamp: "2024-01-01T00:00:09Z",
level: "info",
message: "User logged in successfully",
},
],
};
// With gzip (default) — 195 chars
const withGzip = await HideMyJson.encode(logs);
// → "3ds5WnDJjriKiymY1XNkFDeDIptcHrsMqkvI5tyPC6qLVvmKj0A5daZlEkx97fhvkVoAO56jxG2bLhASkStsdDwanA39knKUK2gkFHkTUgJnqncDBa9bZgCFowDicGkFqNhVrRxtsQOhKHLXqR3d66nfShjLGfAAxMSvneVwMwno2e17Jbmzt8HBbz525p7O3QO"
// Without gzip — 1250 chars
const withoutGzip = await HideMyJson.encode(logs, { useGzip: false });
// → "4Rj3f1gVDwE2qrEYheA7YwpvuY03umVpPext..." (1250 characters)| Mode | Payload size | | ----------------------- | ------------ | | With gzip (default) | 195 chars | | Without gzip | 1,250 chars | | Original JSON | 930 bytes |
All Options Combined
const opts = {
xorKey: "my-secret-key",
useGzip: false,
debug: true,
};
const result = await HideMyJson.encode({ hello: "world" }, opts);
console.log(result.payload);
// → "2oBeeu9YmiH3WIT7ibzPNWA"
console.log(result.steps);
// → {
// originalJson: '{"hello":"world"}',
// originalBytes: 17,
// compressedHex: "7b 22 68 65 ...",
// compressedBytes: 17,
// xoredHex: "16 57 1c 0b ...",
// xoredBytes: 17,
// encoded: "9Bx3mKz7Wp",
// encodedBytes: 10
// }Debug Mode
Pass debug: true to inspect every stage of the pipeline:
const result = await HideMyJson.encode(
{ hello: "world" },
{ xorKey: "secret", debug: true },
);
console.log(result.steps);
// → {
// originalJson: '{"hello":"world"}',
// originalBytes: 17,
// compressedHex: "1f 8b 08 00 00 ...", ← gzip output
// compressedBytes: 37,
// xoredHex: "6c ee 6b 72 65 ...", ← after XOR
// xoredBytes: 37,
// encoded: "841SU0Las2ERP...", ← final Base62
// encodedBytes: 50
// }
const decoded = await HideMyJson.decode(result.payload, {
xorKey: "secret",
debug: true,
});
console.log(decoded.steps);
// → {
// encoded: "841SU0Las2ER...",
// encodedBytes: 50,
// xoredHex: "6c ee 6b 72 65 ...",
// xoredBytes: 37,
// compressedHex: "1f 8b 08 00 ...",
// compressedBytes: 37,
// recoveredJson: '{"hello":"world"}',
// recoveredBytes: 17
// }API
HideMyJson.encode<T>(value: T, options?): Promise<EncodeResult>
| Option | Type | Default | Description |
| --------- | ---------------- | ----------- | -------------------------------------------------- |
| xorKey | string \| null | undefined | XOR key for encryption. Skipped if not provided. |
| useGzip | boolean | true | Gzip-compress the data before encoding. |
| debug | boolean | false | Include intermediate pipeline steps in the result. |
Returns { payload, steps? }
HideMyJson.decode<T>(payload: string, options?): Promise<DecodeResult<T>>
Uses the same options as encode. Returns { data, steps? }
Browser Usage (Script Tag)
<script src="https://cdn.jsdelivr.net/npm/hide-my-json/dist/browser.global.js"></script>
<script>
const { payload } = await HideMyJson.encode({ hello: "world" });
</script>Requirements
- Node.js ≥ 18 or any modern browser (requires
CompressionStream/DecompressionStreamAPI whenuseGzip: true)
License
MIT
