Library / SDK
LFDT-web3j/web3j avatar
LFDT-web3j/web3j

Web3j: a Java library for talking to Ethereum nodes

Lightweight Java and Android library for integration with Ethereum clients

5,403 stars1,773 forksJavaNOASSERTION

At a glance

What is it?
Web3j is a Java and Android library for Ethereum JSON-RPC, wallets and smart contract wrappers. It fits JVM backends and Android apps that must stay inside the Java type system, and it costs you Java 21 plus a handful of runtime dependencies.
Who is it for?
Adopt Web3j if you have a JVM or Android codebase that needs typed Ethereum access, contract wrappers generated from Solidity or Truffle artifacts, or ENS resolution without writing JSON-RPC by hand. Skip it if you are not on Java 21, if you need IPC inside an Android build, or if your stack is TypeScript or Python and a Java bridge would be pure overhead.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap Web3j fills between Java code and an Ethereum node

An Ethereum node speaks JSON-RPC. A Java service does not. Bridging the two by hand means writing request builders, serialising parameters as hex strings, parsing responses into your own types, and repeating that for every method you call. Web3j exists to remove that layer. The README describes it as a lightweight, modular, reactive, type safe Java and Android library for working with smart contracts and integrating with clients on the Ethereum network, and the feature list backs that up: a complete implementation of Ethereum's JSON-RPC client API over HTTP and IPC, wallet support, auto-generated Java smart contract wrappers, a reactive-functional API for filters, and ENS support.

The intended audience is narrow and specific. If you are writing a JVM backend that settles transactions, an Android wallet, a custody service, or a test harness that needs to deploy contracts from a build script, the Java type system is where your logic already lives and a native Java client avoids a language boundary. If your product is a web frontend or a Python data pipeline, Web3j is the wrong shape: you would be adding a JVM process purely as a transport.

The project sits under the Hyperledger umbrella (the README notes that since Web3J moved under Hyperledger, contributor calls happen every two weeks) and the repository carries the governance files you would expect from that: MAINTAINERS.md, SECURITY.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md. The last push to the default branch was on 2026-09-22, and the most recent release listed is v6.0.0 from 2026-06-29. That is a live repository, not a frozen one.

How the modules and the JSON-RPC path actually fit together

The repository layout tells you more about the architecture than the prose does. The top level contains core/, crypto/, abi/, rlp/, tuples/, codegen/, utils/, contracts/, plus client-specific directories named besu/, geth/ and parity/, and hosted-providers/ for the managed node services. That split is the design: crypto handles keys and signing, rlp handles the recursive-length-prefix encoding that Ethereum transactions and blocks use, abi handles application binary interface encoding and decoding, tuples supports Solidity struct types, and codegen is the generator that turns a contract definition into Java.

Data flows in two directions. Outbound, you build a request through the typed API, it is serialised to JSON, and it leaves over HTTP or IPC. The README states that JSON serialisation uses Jackson Core and that HTTP connections use OkHttp, so both are on your classpath whether or not you interact with them directly. Inbound, the node's response is deserialised and handed back to you, and for anything subscription-like the reactive-functional API returns RxJava types rather than callbacks. That is why RxJava is listed as a runtime dependency rather than an optional extra: filters and event streams are expressed in it.

The codegen path is the part that changes how a project is structured. You point the generator at a Solidity contract or a Truffle contract schema, and it emits a Java wrapper class with methods for deploy, transact and call. Those wrappers then depend on the abi and tuples modules to encode arguments correctly, including structs. The practical consequence is that your build gains a code generation step, and the generated sources become something you either commit or regenerate. The README does not document how to handle regeneration conflicts, which is worth knowing before you wire it into CI.

Six runtime dependencies are named: RxJava, OkHttp, Jackson Core, Bouncy Castle, Jnr-unixsocket and Java-WebSocket, with JavaPoet used for wrapper generation. Jnr-unixsocket is flagged as not available on Android, which is the clearest architectural boundary in the README: the IPC transport does not exist on that platform, so an Android build is HTTP-only in practice.

Installing Web3j and getting a first project running

There are two entry points. The first is the Web3j CLI, which the README calls the simplest way to start. On Unix the installer is a shell pipeline that downloads and sources an environment script:

bash
curl -L get.web3j.io | sh && source ~/.web3j/source.sh

On Windows the equivalent is a PowerShell one-liner that bypasses the execution policy for the current process and runs a remote installer script. After either, the CLI should be on your path. Running it with no arguments other than the new subcommand scaffolds a project:

bash
web3j new

The README does not document the prompts or the resulting directory structure, so treat the output as something to inspect rather than assume.

The second entry point is a build dependency, which is what most existing projects want. For Maven, the coordinates are groupId org.web3j and artifactId core:

xml
<dependency>
  <groupId>org.web3j</groupId>
  <artifactId>core</artifactId>
  <version>5.0.3</version>
</dependency>

The Gradle form is a single implementation line, `implementation ('org.web3j:core:5.0.3')`. Note the version in these snippets: the README shows 5.0.3 while the release list already includes v6.0.0, so pin deliberately rather than copying the README blindly. Android uses a different artifact and a different line entirely, 4.12.3-android, which is not the same version train as the Java artifact.

One constraint applies before any of this compiles. The README states that the Web3j Java binaries are compiled using Java 21, and that Java 21 or newer is required to use Web3j as a dependency. If your build targets an older bytecode level, you will find out at compile time, not at runtime.

For code generation inside a build rather than through the CLI, the README points at separate Maven and Gradle plugins in their own repositories, which generate Java files from Solidity contracts. Those plugins are the route to take if you want wrappers produced as part of an ordinary build.

Where Web3j is the wrong tool

The Android story is more constrained than the headline feature list suggests. Android is listed as compatible, and there is a dedicated artifact, but the README explicitly marks Jnr-unixsocket as not available on Android. Since that dependency exists for Unix-domain IPC, an Android app cannot use the IPC transport. Everything goes over HTTP. If your architecture assumed a local node reached by socket, that assumption does not survive contact with Android.

The Java 21 requirement is the second hard edge. It is a floor, not a recommendation. Teams maintaining services on Java 17 or Java 11 cannot adopt the current Java artifact without moving their runtime first, and that migration is usually larger than the Ethereum integration itself. The Android artifact at 4.12.3-android is a separate line, so an organisation with both an Android app and a JVM backend is maintaining two dependency versions with different capabilities.

The dependency count is a real cost in constrained environments. Six runtime dependencies including Bouncy Castle and OkHttp is modest for a server but is not free in an Android APK, where method count and package size matter. The README does not publish size figures, so measure rather than estimate.

Finally, the reactive API is a commitment, not a convenience. Filters and event handling are expressed through RxJava. If your codebase has standardised on a different async model, you will be translating at the boundary, and the README does not describe an alternative callback-based surface for those paths. The integration tests offer some mitigation: the README documents that they can be excluded when no live client is available, using `./gradlew -Pintegration-tests=false :test`, which means the build does not require a running node by default.

Web3j against web3.js and ethers.js

The obvious alternative is the JavaScript ecosystem, web3.js or ethers.js. The difference is not feature parity, it is where the code runs and what type safety you get. The JavaScript libraries are the default for browser frontends and Node services, they are written in the same language as most Solidity tooling, and they require no JVM in the deployment. Web3j requires a Java runtime and delivers Java types: generated contract wrappers are classes with methods, not objects with dynamically attached functions.

That distinction matters most in two situations. In a JVM backend where contract calls sit alongside database transactions and message consumers, having the contract surface as compile-checked Java removes a class of runtime errors that a dynamically typed client cannot catch until execution. In Android, a native Java library avoids shipping a JavaScript runtime inside the app, which is a meaningful difference in both size and startup behaviour.

The trade-off runs the other way too. The JavaScript libraries track new Ethereum proposal and tooling changes faster because the surrounding ecosystem is JavaScript-first, and most tutorials, examples and contract tooling assume that environment. Web3j's codegen accepts Solidity and Truffle definition formats, which covers the common cases, but if your toolchain emits something else, you are converting artifacts before you start. For a team whose entire stack is TypeScript, adding Web3j means adding a second language runtime to the deployment for no gain in type safety, since TypeScript already provides it.

Licence position and the cost of keeping up

The repository reports its licence as NOASSERTION, which means the automated detection could not classify it into a known identifier. A LICENSE file exists at the top level, and that file is the authoritative source, not the metadata field. Under Hyperledger, projects are typically Apache-2.0, but the metadata here does not confirm it and this is not a place to guess. Read the LICENSE file before you ship, and if your organisation has a licence allowlist, run the file past whoever owns it. Nothing in the README or the repository listing resolves the question.

Upgrade cost is driven by three things visible in the repository. First, the version split: the README's Maven and Gradle snippets show 5.0.3 while v6.0.0 is the latest release, so the documentation trails the release train and you cannot treat the README as a version reference. Second, the Android line is separate at 4.12.3-android, so Android and JVM upgrades are independent exercises, not one bump. Third, the Java 21 floor means a future minimum-version bump forces a runtime upgrade on you, not just a dependency change.

Code generation adds a smaller but recurring cost. Generated wrappers are build outputs that depend on the codegen module and JavaPoet. When a contract's ABI changes, the wrapper must be regenerated, and the README does not describe a workflow for that. There is a CHANGELOG.md at the top level, which is where to look for breaking changes between the 5.x and 6.x lines before planning an upgrade.

Editorial conclusion

Adopt Web3j if you have a JVM or Android codebase that needs typed Ethereum access, contract wrappers generated from Solidity or Truffle artifacts, or ENS resolution without writing JSON-RPC by hand. Skip it if you are not on Java 21, if you need IPC inside an Android build, or if your stack is TypeScript or Python and a Java bridge would be pure overhead. Before committing, verify three things against your own environment: that your build produces a Java 21 bytecode target, that the artifact coordinates and version you pin actually resolve from your repository mirror, and that your node provider accepts the JSON-RPC methods you intend to call. The Android artifact is versioned separately at 4.12.3-android, so confirm which line your app depends on before you plan an upgrade.

Frequently asked questions

What is Web3j?

Web3j is a Java and Android library for working with smart contracts and integrating with Ethereum clients. It implements Ethereum's JSON-RPC client API over HTTP and IPC, supports wallets and ENS, and can generate Java smart contract wrappers from Solidity or Truffle definitions.

How do I install Web3j with Maven?

Add a dependency with groupId org.web3j and artifactId core. The README shows version 5.0.3, though v6.0.0 is the latest release listed, so pin the version you actually want. The Java binaries are compiled with Java 21, so Java 21 or newer is required.

Does Web3j work on Android?

Android is listed as compatible and there is a separate artifact, org.web3j:core:4.12.3-android. One limitation is documented: Jnr-unixsocket, used for Unix IPC, is not available on Android, so the IPC transport is not an option there.

How do I generate Java smart contract wrappers with Web3j?

The README states that Web3j auto-generates Java smart contract wrappers and supports both Solidity and Truffle definition formats. It points to separate Maven and Gradle plugins for generating Java files from Solidity contracts as part of a build.

How do I build Web3j without running a live Ethereum client?

The README documents that integration tests require a live client and can be excluded. Running ./gradlew check performs a full build excluding integration tests, and ./gradlew -Pintegration-tests=false :test skips them explicitly.

Official sources

  1. Issues
  2. LFDT-web3j/web3j on GitHub
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lfdt-web3j-web3j.svg)](https://hysenlabs.com/projects/lfdt-web3j-web3j)