LuaJIT Decompiler

LuaJIT Decompiler Online

Decompile LuaJIT bytecode back to Lua source. The format standard Lua decompilers refuse to open.

.luac .lua .ljbc
Drop your LuaJIT bytecode file here
Choose file

⚠ Drag-and-drop upload could not load — an ad blocker is most likely blocking it. Please disable your ad blocker and reload the page to upload a file.

How It Works

1

Upload

Drop your compiled Lua file — any extension, the header decides.

2

Detect & Decompile

The magic bytes select the right decompiler for the dialect.

3

Browse

Read the recovered Lua source in your browser.

LuaJIT Bytecode Is Not Lua Bytecode

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:

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.

Why LuaJIT Bytecode Is Harder

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.

Where You Will Meet LuaJIT

Related Tools

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.

Frequently Asked Questions

Why does my .luac file fail in a normal Lua 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.

How do I know if a file is LuaJIT bytecode?

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.

Which LuaJIT versions are supported?

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.

What uses LuaJIT?

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.

Will I get my variable names back?

Only if the file was compiled without stripping debug information. Stripped bytecode keeps no names, so locals come back as generated identifiers.