Published on Sat Aug 22 2026 00:00:00 GMT+0000 (Coordinated Universal Time) by Jacob Cavazos
Zero-knowledge proofs let you prove you know something without revealing what you know. The prover generates a proof. The verifier checks it. The verifier learns nothing except that the statement is true. This is useful for privacy, authentication, and compliance.
Where the proof is generated matters. If the prover runs on a server, the server sees the secret. If the prover runs on the client, in the browser, the secret never leaves the user’s device. This is client-side ZK, and it is the strongest privacy guarantee you can offer a user in a web application.
This article explains client-side ZK as a concept, the tools available for browser-based proof generation, the performance tradeoffs, and the constraints imposed by the browser environment. All tools and limitations discussed here are public knowledge.
What Client-Side ZK Means
A zero-knowledge proof system has three phases. First, a trusted setup or universal setup phase that generates proving and verification keys. Second, a proving phase where the prover takes a witness (the secret), a public statement, and the proving key, and generates a proof. Third, a verification phase where the verifier checks the proof against the public statement and the verification key.
In a server-side architecture, the proving phase runs on the server. The user sends their secret to the server, the server generates the proof, and the server sends the proof to the verifier. The server sees the secret. If the server is compromised, the secret is exposed. If the server logs the secret, intentionally or accidentally, the secret is stored.
In a client-side architecture, the proving phase runs in the browser. The user’s secret stays in the browser’s memory. The browser generates the proof and sends only the proof to the server or verifier. The server never sees the secret. If the server is compromised, the attacker gets proofs, not secrets.
The distinction is about trust. Server-side ZK requires the user to trust the server with their secret. Client-side ZK does not. The user trusts only their own device.
For applications where the secret is sensitive (financial data, identity attributes, credentials), client-side ZK is the difference between a privacy guarantee and a privacy policy. A privacy policy is a promise. Client-side ZK is a cryptographic guarantee.
Why It Matters
The use cases for client-side ZK are the same as for ZK in general, but with a stronger privacy requirement.
Identity proofs. A user wants to prove they are over 18 without revealing their birthdate. A user wants to prove they are a citizen of a specific country without revealing their passport number. A user wants to prove they have a valid credential without revealing the credential itself. In each case, the secret (birthdate, passport number, credential) is sensitive. Generating the proof client-side ensures the secret never reaches a server.
Financial privacy. A user wants to prove they have sufficient funds for a transaction without revealing their account balance. A user wants to prove a transaction is compliant with tax rules without revealing their transaction history. The financial data is sensitive. Client-side proof generation keeps it on the device.
Authentication. A user wants to prove they know a password or a private key without sending it to the server. ZK-based authentication protocols can replace password transmission with proof transmission. Client-side generation ensures the password or key never leaves the browser.
Compliance proofs. A user wants to prove they are not on a sanctions list without revealing their identity. A user wants to prove their transaction is below a reporting threshold without revealing the transaction amount. These are compliance proofs where the underlying data is private. Client-side generation keeps the data private while producing the compliance proof.
In all of these cases, the value of client-side ZK is that the server cannot compromise privacy even if it wants to. The server receives a proof and verifies it. The server cannot extract the secret from the proof. This is the cryptographic guarantee.
Tools for Browser-Based Proof Generation
Several open-source tools support client-side ZK proof generation in the browser — for a detailed guide on generating ZK proofs in the browser, including tools and tradeoffs, see our companion tutorial. They differ in the proving system they use, the performance characteristics, and the maturity of their browser support.
snarkjs. snarkjs is a JavaScript implementation of zk-SNARKs, specifically the Groth16 and PLONK proving systems. It runs in Node.js and in the browser. It is one of the most widely used tools for browser-based ZK proofs.
snarkjs uses WebAssembly for the cryptographic operations, which gives it reasonable performance in the browser. It supports the full workflow: trusted setup, proof generation, and verification. The trusted setup is done ahead of time, and the proving and verification keys are loaded into the browser.
For browser-based proof generation, snarkjs is the most accessible option. The library is well-documented, the API is straightforward, and the proof sizes are small (a few hundred bytes for Groth16). The main limitation is proving time, which can range from seconds to minutes depending on the circuit complexity and the user’s device.
snarkjs is maintained by iden3 and is used in production by several privacy-focused applications.
halo2-wasm. halo2 is a proving system originally developed by the Electric Coin Company for Zcash. It uses the PLONKish arithmetization and does not require a trusted setup (it uses a universal setup via the Halo recursive proof composition). halo2-wasm is a WebAssembly port of halo2 that runs in the browser.
halo2-wasm offers better performance than snarkjs for certain circuit types, particularly circuits with custom gates. The Halo recursion enables recursive proof composition without a trusted setup, which is useful for more complex applications.
The tradeoff is complexity. halo2 circuits are more difficult to write than snarkjs circuits. The arithmetization requires understanding of PLONKish constraints, custom gates, and lookup tables. The browser support is less mature than snarkjs. The library is under active development.
Noir. Noir is a domain-specific language for zero-knowledge proofs, developed by Aztec. Noir compiles to an intermediate representation that can target multiple backends, including halo2 and Plonky2. Noir programs are written in a high-level language that is significantly more readable than raw circuit definitions.
Noir can run in the browser through its WebAssembly compilation target. The Noir compiler and prover can be compiled to WASM, allowing proof generation entirely client-side. The abstraction layer means developers write Noir code, not circuits, which lowers the barrier to entry.
Noir is newer than snarkjs and halo2-wasm, and its browser support is still maturing. The language is designed to be backend-agnostic, which means a Noir program can potentially generate proofs using different proving systems without rewriting the program. This is a significant advantage for future-proofing.
Other tools. Several other tools have browser support or WASM targets. wasm-snark is a WASM compilation of a SNARK prover. circom and snarkjs together can compile circuits written in the circom DSL and generate proofs in the browser. The rapidly evolving nature of the ZK ecosystem means new tools and improvements appear frequently.
Performance Tradeoffs
Client-side ZK is slower than server-side ZK. This is the primary tradeoff. The browser is not an optimal environment for compute-intensive cryptographic operations.
Proving time. Proving time depends on the circuit size, the proving system, and the device’s CPU. In the browser, proving times for non-trivial circuits typically range from a few seconds to several minutes. For a simple identity proof (proving membership in a Merkle tree of a few thousand leaves), proving time might be 2-10 seconds on a modern laptop. For a more complex circuit (proving compliance over a large transaction set), proving time could be minutes.
This is significantly slower than server-side proving, where a server with a powerful CPU and optimized native code can generate proofs in milliseconds to seconds for the same circuits. The browser penalty comes from two sources: WASM is slower than native code (typically 1.5x to 3x slower for compute-heavy workloads), and browser JavaScript engines impose overhead that native code does not have.
Memory. ZK proving is memory-intensive. The prover needs to hold the witness, intermediate polynomials, and the proving key in memory. For large circuits, this can be hundreds of megabytes or gigabytes. Browsers impose memory limits on WASM and JavaScript, which constrains the maximum circuit size that can be proven client-side.
The 4GB WASM limit. WebAssembly has a practical memory limit of 4GB on most browsers. This is because WASM uses 32-bit addressing, which limits the linear memory to 4GB. Some browsers are beginning to support 64-bit WASM (WASM64), but as of 2026, 32-bit WASM is the dominant target, and the 4GB limit is a real constraint.
For ZK proving, the 4GB limit means there is a maximum circuit size that can be proven in the browser. The exact limit depends on the proving system and the circuit structure, but as a rough guideline, circuits that require more than a few hundred megabytes of proving memory are at the edge of what is feasible in current browsers. This constrains the complexity of client-side proofs.
Workarounds exist. Some proving systems support streaming or chunked proving, where the proof is generated in pieces that fit within the memory limit. This adds complexity and proving time but can extend the range of feasible circuits. The WASM64 proposal, when broadly supported, will raise the limit substantially, but it is not yet universally available.
Proof size. Proof size is generally not a concern for client-side ZK. Most SNARK-based proving systems produce proofs of a few hundred bytes to a few kilobytes. These are trivially transmitted from the browser to the server. STARK-based proofs are larger (tens to hundreds of kilobytes) but still manageable.
Verification time. Verification is fast and is typically done server-side. The server receives the proof from the browser and verifies it in milliseconds. This is not a client-side concern.
Client-Side vs Server-Side: When to Use Each
The choice between client-side and server-side ZK depends on the privacy requirements and the performance constraints of the application.
Use client-side ZK when the secret is sensitive and the user should not have to trust the server. Identity proofs, credential proofs, and authentication proofs are prime candidates. The proving time is acceptable (seconds), the circuit sizes are manageable, and the privacy guarantee is essential.
Use server-side ZK when the secret is not sensitive to the user but the proof is still needed, or when the circuit is too large for the browser. Compliance proofs over large datasets, proofs about server-side state, and proofs with complex circuits are better suited to server-side generation. The server sees the data, but the proof is still valid and the verification is still trustless.
Hybrid approaches are also possible. A system might generate part of the proof client-side (the part involving the user’s secret) and part server-side (the part involving public data), then compose the two proofs. This requires recursive proof composition, which adds complexity but can balance privacy and performance.
Browser Environment Constraints
Beyond the 4GB WASM limit, the browser environment imposes several constraints on ZK proving.
No native multi-threading. WASM in browsers does not support shared memory threads in all contexts. Web Workers can provide parallelism, but they require message passing, which adds overhead. This limits the ability to parallelize proving operations, which are often parallelizable in native implementations.
No GPU access. ZK proving can be significantly accelerated by GPUs. Browsers do not provide direct GPU access to WASM. The WebGPU API is emerging and may eventually provide GPU compute capabilities to browser-based applications, including ZK provers, but it is not yet mature enough for production proving.
User experience. A proving operation that takes 10 seconds in the browser is a 10-second freeze for the user, unless it is run in a Web Worker that does not block the main thread. Good client-side ZK implementations run proving in a Web Worker and show a progress indicator. Poor implementations block the UI and make the application feel broken.
Mobile devices. Mobile browsers are significantly slower than desktop browsers. A proof that takes 5 seconds on a laptop might take 30 seconds on a phone. Mobile memory limits are also tighter. For applications targeting mobile users, circuit sizes and proving times need to be designed with mobile constraints in mind.
The Current State and Trajectory
Client-side ZK is practical today for a range of applications, but it is not yet seamless. The tools exist, the performance is acceptable for many use cases, and the privacy guarantees are real. But the developer experience is still rough, the performance is still constrained, and the browser environment still imposes hard limits.
The trajectory is positive. WASM performance is improving. WASM64 will raise the memory limit. WebGPU will eventually enable GPU-accelerated proving in the browser. The proving systems themselves are getting faster, with newer systems like Plonky2 and STARKs offering better performance characteristics — see our ZK proving systems comparison for benchmarks.
The tools are maturing. Noir’s high-level language approach makes circuit development more accessible. snarkjs remains the easiest entry point. halo2-wasm offers power at the cost of complexity — for a full comparison of proving systems, see our ZK proving systems comparison.
For developers building privacy-preserving web applications today, client-side ZK is a viable architecture. The secret stays on the device. The proof is generated in the browser. The server verifies without seeing the underlying data. The privacy guarantee is cryptographic, not policy-based — a principle shared with deterministic AI, where correctness is guaranteed by computation rather than probability. That is the value proposition, and it is available now.
Frequently Asked Questions
What is a client-side ZK proof?
A client-side zero-knowledge proof is a cryptographic proof generated entirely in the user’s browser or device, without sending the underlying secret data to a server. The proof demonstrates that a computation was performed correctly on private data. The server verifies the proof without ever seeing the data itself.
Can ZK proofs run in the browser?
Yes, ZK proofs can run in the browser using WebAssembly (WASM) to execute the proving algorithms. Modern browsers support WASM, allowing client-side proof generation without installing software. Performance depends on the complexity of the proof and the proving system used, but browser-based proving is practical for many applications today.
What are zero-knowledge proofs used for?
Zero-knowledge proofs are used for privacy-preserving authentication, confidential transactions, identity verification, and proving computation correctness without revealing inputs. In web applications, they enable users to prove properties about their data, such as age or citizenship, without disclosing the data itself. They are also used in rollups for scaling blockchains.
How fast are browser ZK proofs?
Browser ZK proof generation speed depends on the proving system, circuit complexity, and device hardware. Simple proofs can be generated in milliseconds, while complex proofs may take seconds to minutes. Performance is improving with advances in WASM, WebGPU acceleration, and newer proving systems that reduce computational overhead.
Written by Jacob Cavazos
← Back to blog