arweave-js moved to a Node 22 floor and enforced format 2 writes, so version 1 code needs attention
Browser and Nodejs client for general interaction with the arweave protocol and gateways
At a glance
- What is it?
- ArweaveTeam/arweave-js is the TypeScript SDK for the Arweave network and the permaweb, usable from Node and from browsers through bundles or native ES modules. Version 2.1.0 enforces format 2 writes, version 2.0.1 raised the runtime requirement to Node 22 and shipped a native ES module browser build, and large uploads are explicitly steered to a separate bundles tool.
- Who is it for?
- Use arweave-js if you are building a browser or Node application that writes to the Arweave permaweb and want one SDK for wallets, transactions, blocks and gateway access. Do not use it to push large batches of data transactions, because the project itself points that case at @DHA-Team/ArBundles, and do not assume Bun or Deno support, which the documentation says is not currently working.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 45 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One SDK for a storage network, with a browser build that is not an afterthought
Arweave JS is the JavaScript and TypeScript SDK for interacting with the Arweave network and uploading data to the permaweb, and it works in current browsers and Node.js.
What it covers is broader than a transaction signer. The documentation is organised by object: wallets and keys, transactions with data and wallet to wallet transfers, tags, signing, submission, chunked uploading options, transaction status, transaction lookup and data retrieval, block lookup by indep_hash, the current block, and GraphQL.
The dual target is the interesting engineering decision. A storage network SDK has to work in a browser tab, where a private key may exist only to sign a single transaction, and in a Node service, where it may hold a key for a queue worker. Those two environments have different module systems, different bundling needs and different security assumptions, and the package publishes separate entry points for them.
The package metadata shows the split explicitly. The main entry is the Node build at node/index.js, the browser field points at web/index.js, and the published files are the node, web and bundles directories. There is also a react-native field pointing at the Node build, which is a pragmatic choice rather than a dedicated mobile implementation.
The audience is application developers who need to write to a permanent, content addressed store and who want the protocol details handled for them rather than assembling transactions by hand.
Version 2 raised the floor and changed the write format
The release history is where the adoption risk sits, and it is short and sharp.
The published tags are v2.1.0 from 2026-09-08, whose release note reads Format 2 writes enforced, v2.0.1 from 2026-09-01, whose note reads Node 22+, native ESM browser build, and v1.15.0 from 2024-03-19, whose note is Drop NodeJS v16 Support.
Three changes matter for anyone with an existing integration.
First, the runtime floor. The documentation states that when working with NodeJS a minimum version of 18+ is required, and the v2.0.1 tag goes further, naming Node 22+. If your service runs on Node 18 or 20, upgrading from the 1.x line is not a drop in change.
Second, Bun and Deno are explicitly excluded. The note says they are not currently working, so a team that standardised on a non Node runtime has to stay on version 1 or find another path.
Third, and the one with the longest tail, format 2 writes are enforced as of v2.1.0. Any code path that constructs transactions must now emit the format the network expects, and a mismatch is a rejected transaction rather than a warning.
The gap between v1.15.0 in March 2024 and the 2.x releases in September 2026 is a long silence followed by a rapid set of major changes, which is the pattern of a project where the protocol moved and the SDK had to follow.
The repository is not archived and the last push was on 2026-09-08.
Three ways to load it in a browser, and none of them require a CDN
The browser story has three layers, and the newest one is the most interesting.
The first is the bundle files published on unpkg, usable with a plain script tag:
<script src="https://unpkg.com/arweave/bundles/web.bundle.js"></script>
<!-- Latest, minified-->
<script src="https://unpkg.com/arweave/bundles/web.bundle.min.js"></script>The second is the native ES module build, and this is what v2.0.1 added. The web build is published as native ES modules so browsers can load it directly with a script tag of type module, with no bundler and no bundle file.
It has a single external dependency, bignumber.js, which is left as a bare specifier, and browsers cannot resolve bare specifiers on their own. The fix is an import map:
<script type="importmap">
{
"imports": {
"arweave": "https://unpkg.com/[email protected]/web/index.js",
"bignumber.js": "https://unpkg.com/[email protected]/bignumber.mjs"
}
}
</script>
<script type="module">
import Arweave from 'arweave';
</script>The third point is the one teams should actually plan around. The documentation is explicit that nothing here requires a CDN, and that both files can be served from your own origin by copying the web/ directory and the bignumber.mjs file out of the package and pointing the import map at your own paths.
That is a meaningful improvement for a browser SDK that signs transactions. A CDN script tag is a supply chain dependency sitting between your page and a private key, and the self hosted import map removes it without asking you to set up a bundler.
One init object decides whether you talk to a node or a gateway
Initialisation is a single call, and the options object is the whole configuration surface.
In Node, the SDK is imported with require and can point either at a local node or at a gateway:
const Arweave = require('arweave');
// If you want to connect directly to a node
const arweave = Arweave.init({
host: '127.0.0.1',
port: 1984,
protocol: 'http'
});In the browser, the same call with no options uses the current URL path, which the documentation recommends when running from a gateway:
import Arweave from 'arweave';
// Since v1.5.1 you're now able to call the init function for the web version without options. The current URL path will be used by default. This is recommended when running from a gateway.
const arweave = Arweave.init({});The option set itself is short, and the defaults are visible in the documentation:
{
host: 'arweave.net',// Hostname or IP address for a Arweave host
port: 443, // Port
protocol: 'https', // Network protocol http or https
timeout: 20000, // Network request timeouts in milliseconds
logging: false, // Enable network request logging
}So a caller chooses a host, a port, a protocol, a request timeout in milliseconds, and whether network request logging is on. There is no API key configuration in that list, which is consistent with the Arweave model where the identity of the requester is the signing key rather than a credential.
Wallets and keys, where the documentation is unusually firm
The wallets and keys section generates a new wallet address and private key in JWK format, and it carries the warnings you would hope for.
The documentation says not to expose private keys or make them public, because anyone with the key can use the corresponding wallet, and to make sure they are stored securely because they can never be recovered if lost. It also notes that once AR has been sent to the address of a new wallet, the key can then be used to sign outgoing transactions.
That last point has a practical consequence for the order of operations in an onboarding flow. A freshly generated wallet has no balance, so a flow that generates a key and immediately tries to upload a paid transaction will fail until the address has been funded. Generating a key on the client and asking the user to fund it before upload is the sequence the documentation implies.
The generation call returns the key object:
arweave.wallets.generate().then((key) => {
console.log(key);
// {
// "kty": "RSA",
// "n": "3WquzP5IVTIsv3XYJjfw5L-t4X34WoWHwOuxb9V8w...",
// "e": ...
});And a key can be turned back into its address, which is what you store when you want to check a balance or find the last transaction:
arweave.wallets.jwkToAddress(key).then((address) => {
console.log(address);
//1seRanklLU_1VTGkEk7P0xAwMJfA7owA1JHW5KyZKlY
});The same section covers getting an address balance and getting the last transaction id from a wallet.
For a browser application that generates keys, the correct architecture is to keep the key in memory for the duration of one signing operation and never write it to storage you do not control. The documentation does not prescribe that architecture, but the warnings point clearly in that direction.
Two compiled outputs and four tsconfigs behind one package
The build system explains how a single source tree produces a Node package, a web package and browser bundles.
The scripts split into compile:node and compile:web, each running the TypeScript compiler with declarations against its own project file and then resolving the path aliases, and bundle:web and bundle:web-prod, which invoke webpack with named configurations. The production bundle variant is what the unpkg bundle files are.
The repository root carries tsconfig.json plus tsconfig.node.json, tsconfig.web.json and tsconfig.webtests.json, so the Node build, the web build and the web test build are three separate compilations with three separate configurations. There is a webpack.config.js for the bundle outputs and a package script that produces a bundle profile and runs a bundle analyser against it.
The packaging step assembles the published directories from the compiled output and then bundles the web build, and the clean scripts remove the dist, package and bundle directories separately. The prepublish hook runs a clean and a full build, so a published artifact is always a fresh build.
Testing is Mocha over the test directory for the common code, with a separate test:web script that rebuilds the web bundle, builds a webpack test configuration and opens the test page in a browser. That split mirrors the package split, which is the right shape for a library that behaves differently in the two environments.
Two directories at the root are worth noticing for anyone who wants to poke at the protocol rather than use the SDK: debug-cli/ and bin/. A debug command line tool and a bin directory suggest you can inspect transaction and network behaviour without writing a script.
MIT terms, and the boundary the project draws around large uploads
The licence is MIT, which means you can use the SDK inside a commercial product, including a hosted service, without a licensing negotiation.
The scope limit is stated at the very top of the documentation, before the installation section, and it is worth taking seriously. If you are planning to upload large batches of data transactions, the project says it is strongly advised to use @DHA-Team/ArBundles instead of transactions with Arweave.js, with a link to a wiki page explaining bundles and their advantages.
That is an architectural boundary rather than a bug. A bundle is a container format that packs many transactions into one, which is the efficient way to put a large body of data on the network. The SDK is the tool for individual transactions, and pushing batches through it one at a time is the wrong shape for the job.
The other boundary is the runtime one already covered: Node 18 or newer as documented, Node 22 for the v2 line, and no Bun or Deno.
There is also a version skew to keep in mind when you read the browser examples. The import map and script examples in the documentation point at version 2.0.0 URLs, while the newest tag is v2.1.0, and the bundle examples in the table of contents reference an older 1.2.0 URL as an illustration of the versioned form. Pin deliberately rather than copying an example verbatim, especially since v2.1.0 enforces format 2 writes.
Editorial conclusion
Use arweave-js if you are building a browser or Node application that writes to the Arweave permaweb and want one SDK for wallets, transactions, blocks and gateway access. Do not use it to push large batches of data transactions, because the project itself points that case at @DHA-Team/ArBundles, and do not assume Bun or Deno support, which the documentation says is not currently working. Before upgrading an existing integration, check your Node version against the 22 plus requirement in version 2, confirm your write path emits format 2 transactions, and test the wallet key handling in isolation, because a lost private key cannot be recovered.
Frequently asked questions
What is arweave-js?
It is the JavaScript and TypeScript SDK for the Arweave network, covering wallets and keys, transactions, tags, signing, submission, chunked uploading, transaction and block lookup, and GraphQL. It provides separate Node and browser builds and is MIT licensed.
How do I install arweave-js in a browser without a bundler?
Use the native ES module build with an import map. The web build has one external dependency, bignumber.js, left as a bare specifier, so the import map must map both arweave and bignumber.js to URLs. The documentation also shows how to serve both from your own origin instead of a CDN.
What Node.js version does arweave-js need?
The documentation states a minimum of Node 18 for Node.js work, while the v2.0.1 release is labelled Node 22+. Bun and Deno are stated as not currently working.
How do I upload large batches of data transactions with Arweave?
The project advises against using Arweave.js for large batches of data transactions and points to @DHA-Team/ArBundles instead, with a wiki page explaining bundles and their advantages.
What changed in arweave-js v2.1.0?
The v2.1.0 release note reads Format 2 writes enforced. The preceding v2.0.1 release brought Node 22 plus support and a native ESM browser build, while v1.15.0 in March 2024 had dropped Node 16 support.
How do I create a wallet and derive its address in arweave-js?
arweave.wallets.generate() returns a new JWK key, and arweave.wallets.jwkToAddress(key) returns the address for a key. The documentation stresses that private keys must never be exposed or made public and can never be recovered if lost.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/arweaveteam-arweave-js)Was this useful?