People monetizing Android scripts keep running into the same problems: the script gets copied, the card key gets bypassed, and the logic gets changed and passed on. The previous piece covered network-verified card keys. This one covers compile-time code obfuscation: after the code is taken, reading it costs a lot of effort.
What obfuscation is, and how to install it
Obfuscation adds junk instructions and changes control flow while JavaScript compiles. Behavior stays the same. Reading gets harder. Control-flow flattening turns straight-line execution into state-machine jumps, so the path is hard to reconstruct. String arrays scatter plain-text strings into an array and fetch them back at runtime, so a keyword search does not land on them. Dead-code injection inserts noise that never runs and still looks like real code. RC4 encoding encrypts the string array, so static analysis sees ciphertext.
The toolchain needs two things: Node.js (javascript-obfuscator runs on Node) and javascript-obfuscator (the obfuscation library, installed globally with npm). In cmd or PowerShell:
npm install -g javascript-obfuscator
npm install -g class-validator
After install, run npm root -g to see the global install path. The config below uses it.
obfuscator.json field by field, off in development and on at release
After the EC IDEA tools are upgraded to 9.4.0, an obfuscator.json file is created automatically under the project module. Obfuscation is off by default. It starts working only after binPath in the JSON (that is, obfuscatorBinPath) is set correctly. The official default config (tested and runnable):
{
"nodeBinPath": "D:\\programe\\nodejs\\node.exe",
"obfuscatorBinPath": "C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\javascript-obfuscator\\bin\\javascript-obfuscator",
"target": "node",
"compact": false,
"log": true,
"optionsPreset": "high-obfuscation",
"deadCodeInjection": false,
"simplify": false,
"seed": 10,
"controlFlowFlattening": true,
"controlFlowFlatteningThreshold": 1,
"unicodeEscapeSequence": false,
"stringArray": true,
"stringArrayRotate": false,
"stringArrayShuffle": false,
"stringArrayThreshold": 1,
"stringArrayWrappersCount": 5,
"stringArrayEncoding": ["rc4"],
"stringArrayCallsTransform": false,
"selfDefending": false,
"splitStrings": false,
"splitStringsChunkLength": 1
}
Note:
//comments in the config are there to explain the fields. Delete them when you use the file, or it will error.
Path settings (required):
| Property | Role |
|---|---|
nodeBinPath |
Path to node.exe |
obfuscatorBinPath |
Path to the javascript-obfuscator executable |
After Node.js is installed, the global install path is usually C:\Users\<username>\AppData\Roaming\npm\node_modules. Find javascript-obfuscator inside node_modules and copy the full path. Obfuscation strength (the important part):
| Property | Default | Role |
|---|---|---|
optionsPreset |
high-obfuscation |
Obfuscation-level preset |
controlFlowFlattening |
true |
Control-flow flattening, breaks up execution order |
controlFlowFlatteningThreshold |
1 |
Flattening ratio, 1 = all of the code |
deadCodeInjection |
false |
Dead-code injection, can be on or off |
simplify |
false |
Code simplification (the opposite direction from obfuscation, leave it false) |
String protection (the important part):
| Property | Default | Role |
|---|---|---|
stringArray |
true |
Pull strings into an array |
stringArrayEncoding |
["rc4"] |
Encoding for the string array. After RC4, static analysis sees only ciphertext |
stringArrayThreshold |
1 |
Share of strings that go into the array, 1 = all of them |
stringArrayWrappersCount |
5 |
Wrapper-function count. More wrappers are harder to restore |
stringArrayRotate / stringArrayShuffle |
false |
Whether to rotate or shuffle the array |
Other controls:
| Property | Default | Role |
|---|---|---|
compact |
false |
Whether to compress the code |
log |
true |
Print obfuscation detail during compilation, so you can confirm it ran |
seed |
10 |
Random seed. A fixed seed makes each obfuscation result reproducible |
unicodeEscapeSequence |
false |
Whether to escape to Unicode |
selfDefending |
false |
Self-defense: formatting the output breaks it (turn on with care, easy to cause collateral damage) |
splitStrings |
false |
Split long strings |
When obfuscation happens: if obfuscator.json has obfuscatorBinPath set and the file exists, compilation obfuscates, including js mode and dex mode. Delete the obfuscatorBinPath value, or delete obfuscator.json, and compilation does not obfuscate. Obfuscation uses a lot of computer resources. Turn it off for everyday debugging, and turn it on when you publish or package. Leave it on during development and every compile is slow, and the obfuscated code is also hard to debug.
Use it together with card keys and fingerprints
Obfuscation on its own does not stop someone who is determined. The official recommendation is to use several measures together. Network-verified card keys: the card is bound to a device, with a heartbeat check, and without a card it does not run. Obfuscate the critical code again, such as the license check and the core algorithm. You do not have to obfuscate the whole package. Package name, apk, and script fingerprint checks require an upload record on each package, and they guard against repackaging and tampering. Critical business can also live in remote variables and remote JavaScript. If you find a crack, swap the remote code and stop the script. Some people also put destructive code in a remote variable, such as formatting the sdcard or deleting contacts. Think through the consequences before that fires.
Once nodeBinPath and obfuscatorBinPath are both set, obfuscation takes effect. Tune the other parameters from the tables above. The default high-strength setup is control-flow flattening, string arrays, and RC4 encoding. Off during development, on at release. What obfuscation raises is the cost of reading. It cannot guarantee the script stays uncracked forever.
About EasyClick: A mobile automation script development platform covering three phone ecosystems: Android without root, iOS without jailbreak, and HarmonyOS. It also offers Apple script writing, Apple cluster control, Android cluster control, remote cloud control, and AI phone cluster control. → Explore all products
Ready to build it for real?
Every approach in this article can be built with EasyClick capabilities on iEasyClick — full documentation, developer tools and automation products, free to try.