Coverage How it works Pricing WAF Detector go-fAST Docs Blog

Open source · MIT · Pure Go

go-fAST

A super-fast JavaScript parser, transformer and code generator for Go.

Turn JavaScript into a typed AST, rewrite it in plain Go, and print it straight back to source. No Node process, no engine to embed - it compiles into your binary and runs anywhere Go does. It is the engine we reach for when we take apart obfuscated anti-bot scripts, and it is free for anyone to use.

$ go get github.com/t14raptor/go-fast
MIT licensed
Pure Go · no cgo
Arena-backed parser
Scope-aware

Benchmarks

Rust-class speed, in pure Go

On a full parse, transform and generate cycle, go-fAST runs in the same league as the fastest Rust toolchains, and comfortably more than 10x ahead of Babel or the next Go parser. Lower is better.

Fastest in Go13× quicker than the next Go parser, tdewolff/parse
≈ OXCwithin ~24% of the fastest Rust parser, end to end
10× fasterthan Babel, the JavaScript standard
Full pipeline · parse + transform + generate
OXC Rust6.47ms
go-fAST (PGO) Go8.00ms
SWC Rust12.50ms
@babel JS79.70ms
tdewolff/parse Go104.82ms
ToolLangParseTraverseCodegenFull pipeline
OXCRust4.18ms0.59ms1.55ms6.47ms
go-fAST (PGO)Go4.30ms1.13ms2.05ms8.00ms
SWCRust7.85ms0.71ms3.90ms12.50ms
@babelJS40.5ms9.9ms22.6ms79.7ms
tdewolff/parseGo95.04ms1.92ms5.70ms104.82ms

Full parse, transform and code generation over a representative JavaScript file; the bar chart is scaled to the slowest tool. go-fAST is built with profile-guided optimisation (PGO). Times vary with input and hardware.

Three things, done fast

Parse. Transform. Generate.

A single, cohesive toolkit for the whole round-trip from JavaScript source to a typed tree and back again.

01 / PARSE

Source to AST

One call - parser.ParseFile - turns a source string into a fully typed *ast.Program, ready to inspect or rewrite. It copes with the messy, modern JavaScript you actually meet in the wild.

02 / TRANSFORM

Walk and rewrite

Embed ast.NoopVisitor, override the handful of node types you care about, and mutate the tree in place. Everything else is walked for you, so a transform stays as small as the change it makes.

03 / GENERATE

AST back to source

Print any node back to JavaScript: readable with generator.Generate, compact with GenerateMinified, or shaped to your own rules through GenerateWithOptions.

In practice

The full round-trip in one file

Parse a snippet, walk the tree with a visitor that renames an identifier, then print the result. That is the entire shape of a go-fAST program.

main.go
package main

import (
	"fmt"

	"github.com/t14raptor/go-fast/ast"
	"github.com/t14raptor/go-fast/generator"
	"github.com/t14raptor/go-fast/parser"
)

// renamer rewrites every identifier named "a" to "answer".
type renamer struct {
	ast.NoopVisitor
}

func (r *renamer) VisitIdentifier(n *ast.Identifier) {
	if n.Name == "a" {
		n.Name = "answer"
	}
	n.VisitChildrenWith(r.V)
}

func main() {
	// 1. Parse JavaScript into a typed AST.
	program, err := parser.ParseFile(`const a = 6 * 7; console.log(a);`)
	if err != nil {
		panic(err)
	}

	// 2. Walk the tree with a visitor and rewrite it.
	v := &renamer{}
	v.V = v
	program.VisitWith(v)

	// 3. Print the transformed source back out.
	fmt.Println(generator.Generate(program))
	// const answer = 6 * 7;
	// console.log(answer);
}

Why go-fAST

Reasons it earns its keep

Not a wrapper around someone else's runtime. A focused, native-Go toolkit with a few things going for it.

RUNS ANYWHERE GO RUNS

No runtime to babysit

Pure Go, no cgo and no JavaScript engine to embed. It compiles into your binary, so you ship one static executable to a CLI, a service or a Lambda - there is no Node process to install or keep alive beside it.

FAST BY DESIGN

Arena-backed parsing

The parser bump-allocates nodes into pre-sized arenas instead of scattering them across the heap, so building even a large tree stays light on allocations and easy on the garbage collector.

SCOPE-AWARE

An in-built scope resolver

One call to resolver.Resolve walks the tree and stamps every identifier with a scope context, binding each reference to the exact declaration it belongs to across function, block and class scopes, hoisting and all. Two different variables both named a are never confused, so you can rename and fold code without breaking it - the safety net real deobfuscation depends on.

TYPED END TO END

The compiler has your back

Every node is a concrete Go struct with typed fields. Your editor autocompletes the tree, and a wrong transform fails to compile instead of blowing up at runtime.

SMALL SURFACE

Learn it in a sitting

Three entry points: parse, a visitor, generate. There is no config object to memorise and no plugin graph to assemble before you can get useful work done.

PROVEN IN PRODUCTION

Battle-tested daily

It is the engine behind our own anti-bot work, run every day against live, hostile, obfuscated JavaScript. What you build on is what we depend on.

What it is for

Built for taking JavaScript apart

If your Go program needs to understand, rewrite or emit JavaScript, go-fAST is the layer underneath it.

DeobfuscationUnpack packed and obfuscated scripts by simplifying the tree.
Static analysisTrace data flow, find sinks, fingerprint behaviour without executing.
CodemodsApply mechanical, repeatable rewrites across a codebase.
MinificationRe-emit a normalised, whitespace-stripped version of any tree.
LintingWalk the AST and flag patterns you care about.
TranspilationLower newer syntax into a form you control.

Star it, fork it, build on it

go-fAST is open source and MIT licensed. Grab it from GitHub, read the docs, or come ask questions in the Discord.

FAQ

Questions

What is go-fAST?+

An open-source Go library for parsing, transforming and generating JavaScript Abstract Syntax Trees. You parse source into a typed AST, walk and rewrite it in plain Go, then print it back to JavaScript. It runs no JavaScript itself, and is built for code analysis and (de)obfuscation.

Is it free and open source?+

Yes. go-fAST is MIT licensed and developed in the open at github.com/T14Raptor/go-fAST.

Do I need Node.js or a JavaScript engine?+

No. go-fAST is pure Go with no cgo and nothing to embed. go get it and it compiles straight into your binary, so there is no runtime to install or separate process to manage.

Does it run the JavaScript, like goja or otto?+

No. goja and otto are interpreters that execute JavaScript inside Go. go-fAST never runs the code; it hands you the syntax tree to inspect, rewrite and print. Reach for it when the goal is to analyse or transform JavaScript rather than execute it.

What can I build with it?+

Minifiers, deobfuscators, static analysers, codemods, linters and transpilation passes. It is the parser we reach for when reverse-engineering anti-bot scripts, which is what the DISASM API is built on.

How do I install it?+

Run go get github.com/t14raptor/go-fast. It requires Go 1.24 or newer.