Decompile LuaJIT bytecode back to Lua source. The format standard Lua decompilers refuse to open.
Drop your compiled Lua file — any extension, the header decides.
The magic bytes select the right decompiler for the dialect.
Read the recovered Lua source in your browser.
This trips up almost everyone. LuaJIT is a separate implementation of the Lua language with its own compiler, its own instruction set and its own bytecode container format. A file produced by luajit -b has nothing in common with one produced by luac beyond the language it started as.
The two are trivially distinguishable by their first bytes:
1B 4C 75 61, that is \x1b followed by Lua, then a version byte such as 0x51 for Lua 5.1.1B 4C 4A, that is \x1b followed by LJ, then a bytecode version byte.Because both are routinely saved with a .luac extension, an extension-based tool sends LuaJIT files to a decompiler that cannot possibly read them, and you get an unhelpful parse error. This site reads the header instead of the filename, so a LuaJIT file is routed to a LuaJIT decompiler even if it is named .lua.
LuaJIT's instruction set was designed for a tracing JIT compiler, not for readability. It has considerably more opcodes than standard Lua, many of them specialised fast paths for common patterns — dedicated instructions for numeric for loops, for table access with constant string keys, for comparison-and-branch fused into one operation.
Those fused instructions are good for the JIT and awkward for a decompiler, because one bytecode instruction can correspond to several lines of source, and the mapping is not always unique. Recovering readable source is therefore a reconstruction rather than a straight inversion, and the output is usually correct but not byte-identical to what was written.
LuaJIT 2.1 made this harder again. Its bytecode dropped some of the redundancy 2.0 carried, so 2.1 files — especially ones compiled with -s to strip debug information — can leave gaps that no decompiler currently recovers. Where the debug info survives, variable names and line numbers come back with it.
lua-nginx-module ecosystem runs on LuaJIT, and precompiled bytecode is a common deployment choice.assets/. Upload the APK and open it from there.If your file turns out to be standard Lua bytecode, the Lua decompiler handles Lua 5.0 through 5.4. If it is Roblox bytecode, that is a third format again — see the Luau decompiler.
Because it is probably LuaJIT bytecode, not standard Lua bytecode. The two formats are unrelated despite sharing the .luac extension. LuaJIT files start with \x1bLJ; standard Lua files start with \x1bLua.
Check the first three bytes for \x1bLJ. You do not need to do this manually here — the format is detected from the header automatically and routed to the right decompiler.
LuaJIT 2.0 decompiles reliably. LuaJIT 2.1 is supported, but its bytecode changed in ways that make some constructs harder to reconstruct, so expect occasional gaps.
OpenResty and Nginx scripting, Garry's Mod, Don't Starve, Factorio mods, many mobile games built on Corona or Defold, and a great deal of embedded network equipment.
Only if the file was compiled without stripping debug information. Stripped bytecode keeps no names, so locals come back as generated identifiers.