FaceX: a full face pipeline in WebAssembly, with the weights shipped as ciphertext
Full face stack that runs entirely in the browser. Detection, 576-point 3D mesh, recognition, anti-spoof, smile — all WebAssembly, zero server. Apache 2.0.
At a glance
- What is it?
- FaceX packages detection, a 576-point 3D mesh, recognition and passive anti-spoof into one C codebase that runs in the browser or natively. The interesting part is not the model list, it is the decision to ship AES-256-GCM encrypted weights and decrypt them with WebCrypto.
- Who is it for?
- Adopt FaceX if you need face matching that never leaves the device and you are willing to own the biometric consent and retention rules yourself, or if you want a small C library with no Python and no FFmpeg in the dependency graph.
- Can I use it commercially?
- Yes. Apache-2.0 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 124 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem FaceX targets: face matching without a round trip
Most face recognition integrations end up as an HTTP call. You capture a frame, POST it to a vendor, and get back a similarity score or an identity. That shape brings three costs: per-call pricing, network latency, and the fact that a biometric template of your user now exists on someone else's infrastructure. FaceX is built to remove all three. The README describes it as a full face stack that runs entirely in the browser, with detection, landmarks, a dense 3D mesh, recognition and passive anti-spoof all compiled to WebAssembly and no server component. The stated audience is concrete: KYC selfie-to-ID matching, offline face login, door and turnstile access control on edge hardware without a GPU, exam proctoring, and in-store kiosks on cheap SoCs. The cost table in the README puts a 100,000-user app doing one match per session per day at $0 with FaceX against $3,000 to $4,500 per month for AWS Rekognition, Azure Face or Google Vision at $1.00 to $1.50 per thousand matches. Treat that table as the project's own arithmetic, not an audited comparison, but the direction is the point: the marginal cost of a match is zero because the match happens on the user's CPU.
Five models, one pipeline, and where the bytes actually go
The README lists the components and their provenance in one table, which is unusually specific for a project of this size. The detector is a YuNet-style FCOS model trained on WIDER FACE at 401 KB. Landmarks are 98 points trained on WFLW at 1.1 MB. The 3D mesh is 576 points at 5.6 MB, distilled from MediaPipe. Recognition comes in four sizes between 0.8 MB and 8.4 MB, built on MobileFaceNet plus ArcFace trained on MS1M, reporting LFW accuracy from 95.62 percent up to 99.07 percent as a 10-fold mean. Anti-spoof is the one component not written by the authors: two MiniFASNet models at 1.7 MB each, from MinivisionAI Silent-Face, Apache 2.0. Total shipped weight is around 17 MB in the WASM path. The data flow is a straight chain: frame in, detector produces a box, landmarks and mesh refine the alignment, recognition emits a 512-float embedding, and similarity is a comparison between two embeddings. The anti-spoof models sit alongside as a separate gate rather than inside the embedding path, which matters because you can run recognition without liveness if your threat model does not include printed photos or a phone screen held to a camera.
Encrypted weights: what AES-256-GCM actually buys you here
This is the design choice worth arguing about. FaceX ships its model weights as AES-256-GCM ciphertext and decrypts them in the browser through WebCrypto. The README is direct that this is not DRM and that a determined attacker can dump the decrypted bytes from the WASM heap. So what does it do? Three things, per the documentation: friction against casual scraping of the weight files, per-customer key revocation for SaaS deployments, and an audit trail at the key-issuing endpoint. That is an honest framing, and it is more useful than most obfuscation claims. If you are shipping a commercial product on top of FaceX, the revocation path is the real feature. If you are shipping an open client, the encryption is mostly ceremony, since the key must reach the client anyway. The wiki is said to cover the threat model plus Express and FastAPI integration recipes for issuing keys, which is the part you would need to read before designing your own key distribution.
Getting it running: the native call and the browser demo
The README gives a C example that is short enough to quote in full. You include facex.h, call facex_init with a weights file path and a null second argument, then call facex_embed on a 112x112 face crop to fill a float array of 512 values, and facex_similarity on two embeddings returns a float where the README states greater than 0.3 means same person. The browser path is a static server: clone the repository, change into the wasm directory, run python -m http.server 8000, and open demo_mesh.html at 127.0.0.1:8000. There is a hosted demo at facex-engine.github.io/facex/demo that the README says needs a Chromium browser and a camera. Note what is not in the material: there is no npm package name, no bundler configuration, no documented JavaScript API surface beyond the demo page. If you are integrating into a web app rather than running the demo, the wiki is where that would have to come from.
Where FaceX is the wrong tool
The 0.3 similarity threshold is a fixed default, and the README does not describe a calibration procedure or a per-deployment tuning guide. Every face system has an operating point that trades false accepts against false rejects, and a single number in a code comment is not that. If your application has a regulatory accuracy requirement, you would need to measure equal error rate on your own population before trusting the default. The second limitation is the benchmark itself. LFW at 99.07 percent is a 10-fold mean on a dataset of aligned, mostly frontal, well-lit faces. It says very little about a webcam at a kiosk with overhead lighting and a user wearing a mask. The README does not report accuracy under those conditions. Third, the mesh and the anti-spoof models are the largest weights in the bundle, so a deployment that only needs detection plus recognition is carrying megabytes it will not use unless it can prune the weight file. The material does not describe a build-time pruning step. Finally, the platform table shows Apple Silicon, ARM Linux and Android as shipping in PR #3, and the NPU and ESP32 targets as drafts. If your target is an i.MX or an ESP32-P4 today, you are reading a roadmap, not a release.
The alternative: onnxruntime-web with your own models
The closest practical alternative is not a competing face SDK, it is assembling the same pipeline yourself from ONNX models and running them through onnxruntime-web. The difference is in what you inherit. With onnxruntime-web you get a maintained runtime with a documented JavaScript API, a large model zoo to choose from, and the freedom to swap the detector or the embedding model without touching C. What you do not get is a single coherent pipeline with a shared alignment convention, a fixed 512-float embedding space, and a similarity threshold that the authors have at least put a number on. FaceX's own README frames the runtime question directly: it lists nn2, the project's inference engine, as replacing onnxruntime at 1.5 to 2 times the speed on a 320-pixel input at 8.5 ms. That is the project's claim about its own engine, not an independent measurement. The practical split is this: if you want to iterate on models, onnxruntime-web plus your own ONNX files gives you more room. If you want one binary, no Python in the build, and a C API you can flash to firmware, FaceX is the more opinionated and smaller answer.
Maintenance cost and the licence boundary
FaceX is Apache 2.0, which is permissive and includes a patent grant, and the anti-spoof models are also Apache 2.0 from MinivisionAI Silent-Face. The rest of the weights are described as trained by the authors, which means the licence on the code and the provenance of the training data are two separate questions you would need to settle for a commercial deployment, particularly for MS1M-derived recognition models. On maintenance: the repository is not archived, the last push is dated 2026-05-14, and there are two releases, v1.0.0 in April 2026 and facex-nano-1.0 in May 2026. That is a young project with a short release history, and the README itself describes several targets as drafts or in progress. The upgrade cost is dominated by the weight format: if facex_init takes a weights path and the weights are encrypted, any change to the key handling or the weight layout is a change to your deployment pipeline, not just a version bump. Budget for pinning a specific weights file and testing the decryption path on every runtime you support. This is not legal advice; the licence text and the training-data provenance are things to check against your own compliance requirements.
Editorial conclusion
Adopt FaceX if you need face matching that never leaves the device and you are willing to own the biometric consent and retention rules yourself, or if you want a small C library with no Python and no FFmpeg in the dependency graph. Do not adopt it if you need an actively maintained upstream with a long support history, or if your accuracy target sits above the 99.07 percent LFW figure the README reports, since that is a 10-fold mean on one benchmark and not a claim about your own capture conditions. Before writing code, verify two things on your own hardware: that the browser path actually loads the AES-256-GCM weights through WebCrypto on your target Chromium, Firefox or Safari build, and that the native facex_similarity threshold of 0.3 produces the false-accept rate you can live with on your camera and lighting.
Community notes