# Duktape: an embeddable JavaScript engine you build into your C project

> Duktape is an ECMAScript E5/E5.1 engine distributed as amalgamated C sources, aimed at C and C++ projects that need scripting without a large runtime dependency. The main repository is for engine developers, and the master branch is currently heading toward incompatible 3.x changes.

**svaarala/duktape** — Duktape - embeddable Javascript engine with a focus on portability and compact footprint

- Repository: https://github.com/svaarala/duktape
- Stars: 6,215 · Forks: 541
- Language: JavaScript
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/svaarala-duktape

## The problem Duktape solves: scripting inside a C or C++ binary

Duktape exists for programs that already have a build system and a platform target, and want to run JavaScript inside them without pulling in a separate runtime process. The README describes it as an embeddable JavaScript engine with a focus on portability and compact footprint, and the integration path it gives is deliberately small: add duktape.c, duktape.h and duk_config.h to your build, then use the Duktape API to call ECMAScript functions from C code and vice versa.

That shape decides the audience. This is not a tool for running a Node.js application, and it is not a browser engine. It is for firmware, desktop applications, game logic layers, configuration and rule evaluation, and any C or C++ codebase where a scripting layer is useful but a large runtime dependency is not acceptable. The README lists minimal platform dependencies and a built-in regular expression engine, Unicode support and debugger as part of the same package, which matters because each of those would otherwise be another dependency to port.

The engine targets ECMAScript E5/E5.1 with some semantics updated from ES2015 and later. Partial support for ECMAScript 2015 and 2016 is documented through a Post-ES5 feature status page on the wiki and the kangax compat table. If your scripts assume modern syntax as a baseline, that target is the first thing to check, not the last.

## How the amalgamated build works and where your code sits

The distributable src/ directory contains a duk_config.h configuration header and amalgamated sources for the default configuration. Amalgamation is the central design decision here: instead of a library you link against, you compile the engine's C sources as part of your own translation units. There is no separate shared object to ship, and no ABI boundary to negotiate at runtime.

The configuration header is where behaviour is decided before compilation. The README points to a configure tool for producing header and sources for customized options, and gives fastint as an example of a feature that is off in the default configuration and turned on at generation time. That means two builds of Duktape with different configuration options are different binaries, not the same binary with different flags. If you ship a product with a customized configuration, you own the record of which options were used.

The README also states what the engine gives you at runtime: combined reference counting and mark-and-sweep garbage collection with finalization, coroutines as a custom feature, property virtualization using a subset of the ES2015 Proxy object, and bytecode dump and load for caching compiled functions. The distributable is described as including an optional logging framework, CommonJS-based module loading implementations and CBOR bindings. Those extras are optional, so a minimal embedding does not have to carry them.

## Installing Duktape and running a first embedding

The README is explicit about which repository you should use. This repository is intended for Duktape developers only and contains internals such as test cases, internal documentation and sources for the duktape.org web site. End users embedding Duktape are told to use the packaged source distributables from the download page on duktape.org, which are also available from the duktape-releases repository as binaries and as unpacked git tags.

If you use a dependency manager, the README documents a vcpkg port. These commands clone vcpkg, bootstrap it, integrate it and install the duktape package.

```bash
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install duktape
```

If you need a non-default configuration, you unpack a source distributable and regenerate the sources with the configure tool. The README gives this exact sequence for enabling fastint support on Linux, and notes that src-custom/ will then contain duktape.c, duktape.h and duk_config.h.

```bash
tar xvfJ duktape-2.0.0.tar.xz
cd duktape-2.0.0
rm -rf src-custom
python tools/configure.py \
      --source-directory src-input \
      --output-directory src-custom \
      --config-metadata config \
      -DDUK_USE_FASTINT
```

After that, adding the engine to your own project is a build-system change rather than an install step: compile the generated duktape.c alongside your sources and include duktape.h. The README points to the getting started section of the online guide for the basics of the embedding API. It does not document a package manager install for Linux distributions, and it does not describe a rollback procedure if a regenerated configuration misbehaves; you would revert your own build inputs.

If you want to modify the engine itself and rebuild the distributable, the README documents a separate path. On Linux, macOS and Windows this uses util/dist.py and needs Python 2 and the Python YAML binding, with Node.js 16.x or later installed; the resulting source distributable appears in dist/.

```bash
sudo apt-get install python python-yaml
python util/dist.py
```

## The master branch warning, and why pinning is not optional

The README opens with a warning that the master branch is undergoing incompatible changes for Duktape 3.x, and directs anyone tracking Duktape 2.x to the v2-maintenance branch. The branch policy section explains the reasoning: master is used for active development, pull requests are tested before merging but master may still be broken from time to time, and when development on a new major release starts, master gets API incompatible changes without warning. The README's own advice is that you should generally not depend on the master branch, and should use a release tag such as v2.4.0 or a release maintenance branch instead.

This is the sharpest practical constraint in the project. The latest release listed is v2.7.0 from 2022-02-19, after v2.6.0 in 2020 and v2.5.0 in 2019. The release tags are the stable surface. The last push to the repository was on 2026-09-04, so work is ongoing, but that work is on a branch whose compatibility the README explicitly disclaims.

The repository layout reinforces the point. The top level contains src-input, src-tools, tests, testrunner, debugger, doc, website, dukweb, polyfills and misc. This is the machinery for building and testing an engine, not a library tree you vendor directly. Vendoring from this repository means vendoring from the development tree.

## Where Duktape is the wrong tool

The clearest failure case is a project that needs modern ECMAScript as a baseline. Duktape is E5/E5.1 compliant with some semantics updated from ES2015 and later, and support for ES2015 and ES2016 is partial. The README does not promise a date for closing that gap, and the Post-ES5 feature status page exists precisely because the answer is feature by feature. If your scripts come from a modern toolchain, transpilation or rewriting is your problem, not the engine's.

A second case is any workflow that assumes a system package. The README documents vcpkg and the source distributable, and does not document distribution packages. Teams whose deployment model is apt install or an equivalent will be building from source or generating a custom configuration.

The third case is performance-sensitive work where you would otherwise reach for a JIT. Duktape is an interpreter with bytecode dump and load for caching compiled functions, which is a startup-cost optimisation, not a throughput one. The README makes no performance claims, and there is nothing in it to suggest the engine is aimed at workloads where a JIT would be the normal answer.

Finally, note the maintenance cost of the build itself. Rebuilding the distributable needs Python 2 and the Python YAML binding, and the README separately notes that the development Makefile and the Docker images are supported for Linux x86-64 only, with limited macOS support via Docker. A Python 2 dependency in a build path is a real constraint for teams that have moved off it.

## Duktape compared with QuickJS and Lua

The most common comparison is QuickJS, and the difference is not only size. QuickJS targets modern ECMAScript, so the language level you get out of the box is a different generation from Duktape's E5/E5.1 baseline with partial ES2015 and ES2016. Duktape's counterweight is the integration model: three generated files added to your build, a configuration header that fixes engine behaviour at compile time, and a documented set of optional extras in the distributable. If your scripts are already ES5-era, the language gap costs you nothing and the build model is simpler. If they are not, the gap is the deciding factor and Duktape is the wrong side of it.

The Lua comparison is about language choice rather than engine quality. If you are choosing a scripting language for a C or C++ host today, Lua is a smaller language with a long history of embedding, and Duktape's reason to exist is that it gives you JavaScript semantics instead. That matters when the scripts are written by people who already know JavaScript, or when you want to reuse code and knowledge from the JavaScript ecosystem. It does not matter if the scripting layer is internal and the language is an implementation detail.

A comparison with V8 is mostly a category error. V8 is a JIT engine built for browsers and Node.js; Duktape is an interpreter designed to be compiled into a host program with minimal platform dependencies. The README's framing of portability and compact footprint is the whole argument. If you have the memory budget and the platform support for a JIT engine, Duktape's constraints are costs you are paying for nothing.

## Licence and upgrade cost

Duktape is released under the MIT licence, which the README describes as liberal and points to LICENSE.txt for the text. The repository file package.json carries the string SEE LICENSE IN LICENSE.txt and marks the package private, with the name @duktape/duktape-repo and version 2.99.99, so the npm metadata is a placeholder for the repository rather than a published package. The licenses/ directory at the top level holds third-party licence material, which is where to look if you redistribute a build that includes bundled components.

Upgrade cost depends on which branch you track. Staying on a release tag or a maintenance branch such as v2-maintenance means the README's compatibility warning does not apply to you, and an upgrade is a deliberate move between releases. Following master means accepting API incompatible changes without warning, which the README states directly. If you generate a custom configuration, an upgrade also means regenerating duktape.c, duktape.h and duk_config.h and re-checking that your chosen options still exist and still behave the same. Nothing in the README describes a migration guide for configuration options across major versions, so that check is yours to run. This is a description of the project's licensing and release mechanics, not legal advice.

## Conclusion

Adopt Duktape if you are embedding scripting in a C or C++ program and want ECMAScript E5/E5.1 semantics from three files you can add to your own build. Do not adopt it if you need full ES2015+ or current ECMAScript features, or if you expect to track master safely. Before committing, verify which release tag or maintenance branch you will pin, whether your target platform is covered by the configuration options you need, and whether the Post-ES5 feature status page lists the language features your scripts actually use.

## FAQ

### What are the main differences between Duktape and QuickJS, and which one is better?

Duktape is ECMAScript E5/E5.1 compliant with some semantics updated from ES2015 and later, and only partial ES2015 and ES2016 support, while QuickJS targets a newer language level. Duktape's distinguishing feature is its integration model: three generated files added to your build plus a configuration header. Which is better depends on whether your scripts are ES5-era or need modern ECMAScript.

### How does Duktape compare with V8?

V8 is a JIT engine for browsers and Node.js, while Duktape is an interpreter designed to be embedded in a C or C++ program with minimal platform dependencies and a compact footprint. Duktape provides bytecode dump and load for caching compiled functions, which is a startup optimisation rather than a throughput one. The README makes no performance claims for the engine.

### How does Duktape compare with Lua?

The difference is the language, not the embedding model. Duktape gives you JavaScript semantics, ECMAScript E5/E5.1 with some ES2015 and later updates, so scripts written by people who already know JavaScript can be reused. Lua is a separate language choice for the same kind of host program.

### What alternatives to Duktape exist for embedding a scripting engine?

The README does not list alternatives. It documents Duktape's own integration path: add duktape.c, duktape.h and duk_config.h to your build, or install the vcpkg port. Choosing between engines comes down to the ECMAScript level you need and whether you want a JIT engine or an interpreter compiled into your host program.

## Sources

- [Issues](https://github.com/svaarala/duktape/issues)
- [License: MIT](https://github.com/svaarala/duktape/blob/master/LICENSE)
- [README](https://github.com/svaarala/duktape/blob/master/README.md)
- [Releases](https://github.com/svaarala/duktape/releases)
- [svaarala/duktape on GitHub](https://github.com/svaarala/duktape)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/svaarala-duktape
