parity

overview

the parity api is able to decompile lua 5.1-5.5 and luau bytecode back into readable source. currently, it's free (while in beta), with no accounts, and no api keys.

base urlhttps://api.useparity.lol
max upload2 MB per request

endpoints

POST /v1/decompile

decompiles one file. you can send the bytecode as the raw request body (Content-Type: application/octet-stream), or as base64 inside a json object when you want to set options:

fieldtypedescription
scriptstringthe bytecode, raw or base64. gzip it first if you want, we decompress it.
settingsobjectany options from below, e.g. {"methodSyntax": false}

accepts .luac .luauc .txt .bin inputs. returns 200 with your output.

GET /v1/health

returns 200 while the api is up.

options

options go in the settings object of the json body. you can omit a field to use its default.

fieldtypedefaultdescription
inferNamesbooltruenames locals from how they're used (local Part = Instance.new("Part"))
debugNamesbooltrueuses variable names stored in debug info when present
identifierCaseenumautocasing for generated names: auto | pascalCase | camelCase | snake_case
generatedNamesenumdescriptivenaming style when nothing better is known: descriptive | typed | simple
inferTypesbooltrueinfers local types from the operations that use them
inferRobloxTypesbooltrueinfers roblox types from calls like Instance.new
typeAnnotationsbooltruewrites : type annotations where the type is known
methodSyntaxbooltruewrites methods as function t:m() instead of t.m(self, ...)
utf8booltrueutf-8 text in strings instead of byte escapes
headerInfobooltrueadds a comment header with the active settings, a parity watermark, and timings
functionLineInfoenumfunctions-- line: N markers on functions: off | functions | all
functionDebugNamesbooltrueuses function names stored in debug info when present
upvalueCommentsbooltrueadds a comment listing the upvalues each function captures
markInlinedCopiesbooltruemarks functions that were duplicated by inlining
normalizeComparisonsbooltrueputs the variable on the left of comparisons (5 == x becomes x == 5)
compoundAssignmentsbooltruex = x + 1 becomes x += 1 (luau)
removeUselessForStepbooltrueremoves the step from numeric for loops when it's 1
mergeTableLiteralsbooltruerejoins table constructors that were split into chunks
parallelAssignmentsbooltruerebuilds a, b = x, y parallel assignments
inlineTemporariesbooltrueinlines single-use temporaries into the expression that reads them
sugarLocalFunctionsbooltruelocal f = function() becomes local function f()
autoCleanupenumautodead code cleanup level: off | auto | aggressive
removeUnusedLocalsboolfalseremoves locals that are never read
earlyReturnsbooltrueflattens nested ifs into guard clauses
removeUselessReturnbooltrueremoves a trailing bare return
interpolatedStringsbooltruerebuilds `{x}` string interpolations (luau)
loopCompletionDefaultsbooltruehides the extra flags loops use to track break/continue
mathConstantsbooltruewrites known constants as math.pi, math.huge, etc.
preferConstbooltruemarks never-reassigned locals <const> (lua 5.4+)
indentWidthint4spaces per indent level, 0-16

rate limits

you will get 300 requests/minute with the api. going over 300 requests/min will return 429 with a Retry-After header. requests also run concurrently; if the concurrent job queue fills up you will get a 503, and will have to retry in usually around ~1 second.

errors

statuscondition
400body isn't valid bytecode or the json is malformed
413request over 2 MB
429rate limited, see Retry-After?
503job queue full, retry shortly