Introduction
Criptor is a military-grade JavaScript protection system with 9 independent protection layers. It transforms your JavaScript files into protected output that runs identically to the original but is engineered to resist automated tools, AI-assisted reverse engineering, and expert human analysis.
Protection happens entirely server-side. Files are processed in memory and auto-deleted after 10 minutes — your source code is never stored.
Quick Start
1. Upload your files
Go to /app, drag and drop your .js files or a .zip archive.
2. Choose a preset
Select one of the four presets (or customize individual layers in the Advanced section):
| Preset | Use Case | Output Size |
|---|---|---|
| light | Development builds, quick obfuscation | ~8× |
| balanced | Production — recommended for most projects | ~65× |
| maximum | High-value IP, maximum resistance | ~300× |
| stealth | No banners, blends into standard jsobf output | ~220× |
3. Download results
Download individual files or all results as a ZIP archive. Protected files can be used as drop-in replacements for the originals.
Web App
The web app at /app provides a full drag-and-drop interface with:
- Multi-file upload (up to 50
.jsfiles or one.zip) - 4 preset cards with one-click selection
- Advanced accordion: all 17 layer toggles grouped by category
- MBA depth slider (1 = fast, 3 = maximum)
- Per-file download links + "Download All as ZIP"
REST API
The Criptor API accepts multipart form data and returns JSON. All endpoints are available at https://criptor.slimmycode.com.
POST /protect
Submit files for protection. Returns a jobId used to download results.
# Single file, balanced preset curl -X POST https://criptor.slimmycode.com/protect \ -F "files=@app.js" \ -F "preset=balanced"
# Multiple files curl -X POST https://criptor.slimmycode.com/protect \ -F "files=@a.js" -F "files=@b.js" \ -F "preset=maximum"
# ZIP archive curl -X POST https://criptor.slimmycode.com/protect \ -F "files=@project.zip" \ -F "preset=balanced"
# With custom layer overrides (JSON) curl -X POST https://criptor.slimmycode.com/protect \ -F "files=@app.js" \ -F "preset=balanced" \ -F 'layers={"canary":true,"timingOracle":true,"mbaDepth":3}'
Response:
{
"jobId": "4e9e7a7d-0498-4b3e-8dd1-466275fb87d9",
"fileCount": 1,
"files": [
{
"name": "app.protected.js",
"originalSize": 4475,
"protectedSize": 286576
}
]
}
GET /download/:jobId/:index
Download a single protected file by index (0-based). Jobs expire after 10 minutes.
curl -o app.protected.js \ https://criptor.slimmycode.com/download/{jobId}/0
GET /download/:jobId/zip
Download all protected files as a ZIP archive.
curl -o protected.zip \ https://criptor.slimmycode.com/download/{jobId}/zip
GET /health
Server health check. Returns uptime and active job count.
curl https://criptor.slimmycode.com/health → {"ok":true,"jobs":3,"uptime":86400}
Rate limits
| Endpoint | Limit | Window |
|---|---|---|
| /protect | 20 requests | Per IP / hour |
| All other routes | 100 requests | Per IP / 15 min |
Presets
Presets are named collections of layer settings. Passing layers overrides individual settings on top of the chosen preset.
| Preset | VM | MBA depth | jsobf | Sandbox poison | Canary | AI layers |
|---|---|---|---|---|---|---|
| light | off | 1 | on | off | off | banner only |
| balanced | on | 2 | on | on | on | honeypots + directive |
| maximum | on | 3 | on | on | on | all layers |
| stealth | on | 3 | on | on | on | none |
Layer Options
All layer options can be passed as JSON in the layers field of a /protect request. Boolean options default to the selected preset's value.
| Option | Type | Description |
|---|---|---|
| banner | boolean | Copyright + AI directive banner at file top |
| vm | boolean | VM bytecode virtualization with rolling-key encryption |
| mba | boolean | Mixed Boolean-Arithmetic on numeric constants |
| mbaDepth | 1 | 2 | 3 | MBA tree depth (1=fast, 3=maximum) |
| mbaThreshold | 0–1 | Fraction of numeric literals to transform (default 0.8) |
| opaque | boolean | Opaque predicate dead-code injection |
| opaqueThreshold | 0–1 | Fraction of functions that get dead-code blocks |
| stringCipher | boolean | Custom keystream string encryption |
| stringThreshold | 0–1 | Fraction of string literals to encrypt (default 0.9) |
| integrityAnchors | boolean | Tamper-evident hash binding all decryption keys |
| jsobf | boolean | javascript-obfuscator pass (RC4, CFG flattening) |
| signatureBreak | boolean | Break jsobf string-array signature (defeats webcrack) |
| moduleIife | boolean | Wrap output in module IIFE — hides decoders from vmCtx |
| sandboxPoison | boolean | 6-signal sandbox detection + charCodeAt poisoning |
| aiHoneypots | boolean | Fake licensing function decoys |
| aiDirective | boolean | Plaintext __ai_notice / __legal_notice vars at AST top |
| aiDeepDirectives | boolean | Policy objects + scoped per-function notices |
| aiContextExhaustion | boolean | 20-page legal report gate + flood decoy |
| canary | boolean | Differential canary — shadow function with a trapdoor |
| canaryPoisonRate | 0–1 | Probability of injecting a canary per build (default 0.5) |
| adversarialTokens | boolean | Rename internal vars with homoglyphs + BPE confusion |
| adversarialTokenRate | 0–1 | Fraction of eligible identifiers to rename (default 0.3) |
| timingOracle | boolean | Clock jitter detection + silent semantic drift in emulators |
API Reference
Error responses
All errors return JSON with an error string field and an appropriate HTTP status code:
| Status | Meaning |
|---|---|
| 400 | No files uploaded or no .js files found in ZIP |
| 413 | File too large (>5 MB) or too many files (>50) |
| 404 | Job not found or expired (10 min TTL) |
| 429 | Rate limit exceeded |
| 500 | Internal protection error |
Job TTL
Jobs are stored in memory and automatically expire after 10 minutes. Download your files immediately after protection.
FAQ
Is the source code safe when uploaded?
Files are processed entirely in memory server-side and auto-deleted after 10 minutes. Nothing is written to disk or logged.
Does protected code run slower?
No. Protected code runs identically to the original. The VM layer adds a small constant overhead on first function call, negligible for typical workloads.
Why is the output so much larger?
The expansion ratio (typically 8×–300× depending on preset) comes from the VM interpreter, MBA expression trees, dead-code blocks, string cipher runtime, and AI honeypot functions. All of this is necessary for the protection layers to function.
What if protection fails?
Complex syntax (certain generators, async generators, decorators) may not be fully supported by the VM layer. Functions that cannot be virtualized are left in their original form. If you encounter an error, try the light preset which skips the VM layer.
Can I automate protection in CI/CD?
Yes — use the REST API with curl or any HTTP client. A typical CI pipeline:
# In your CI script
RESULT=$(curl -s -X POST https://criptor.slimmycode.com/protect \
-F "files=@dist/app.js" -F "preset=maximum")
JOB=$(echo $RESULT | python3 -c "import sys,json;print(json.load(sys.stdin)['jobId'])")
curl -o dist/app.protected.js \
https://criptor.slimmycode.com/download/$JOB/0