[unmaintained] A WhatsApp (Web) transport for XMPP.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
eta e7f2166cd8 deprecation notice 1 year ago
doc README, LICENSE, and general user friendliness 3 years ago
.dockerignore Switch from Nix to new Dockerfile that builds static executables 2 years ago
.gitignore nix: add Nix derivation for whatsxmpp (yay!) 3 years ago
Dockerfile old dockerfile changes? 1 year ago
LICENSE relicense to MIT, screw AGPL 2 years ago
Makefile make more deployable, support XEP-0144 for BIG contact 3 years ago
README.md deprecation notice 1 year ago
component.lisp Message Archive Management (MAM) support for groupchats 2 years ago
db.lisp Expand 'getroster' command to include groupchat subjects 2 years ago
fixup_1.sql add fixup_1.sql, which corrects the UNIQUE error on user_contacts 3 years ago
fixup_2.sql Introduce user & global archiving controls; add unregister function 2 years ago
logo.png README, LICENSE, and general user friendliness 3 years ago
media.lisp Upload and send images natively (!); don't block on QR code 2 years ago
message.lisp Invite users to chats they're not in when messages are sent in those chats 2 years ago
namespaces.lisp Message Archive Management (MAM) support for groupchats 2 years ago
packages.lisp IQ handlers, XEP-0363 stuff, and SQLite, oh my! 3 years ago
schema.sql Introduce user & global archiving controls; add unregister function 2 years ago
sqlite.lisp sqlite: attempted fix for persistent MISUSE errors 2 years ago
stuff.lisp Experimental call notification support 2 years ago
utils.lisp Message Archive Management (MAM) support for groupchats 2 years ago
whatsxmpp.asd Message Archive Management (MAM) support for groupchats 2 years ago
xep-0030.lisp add MUC disco#items handler, fix children including text DOM nodes 3 years ago
xep-0115.lisp Fix order of entity caps in hash function 3 years ago
xep-0313.lisp Message Archive Management (MAM) support for groupchats 2 years ago
xep-0363.lisp fix borked XEP-0363 2 years ago
xmpp.lisp Upload and send images natively (!); don't block on QR code 2 years ago


Note: no longer maintained!

This software isn't maintained any longer. It had a good run, but I eventually decided to go back to just using official WhatsApp clients.

It probably won't work any more; at the time of writing, WhatsApp were rolling out a new beta version of WhatsApp Web that supported connecting to WhatsApp directly without going via your phone, which is totally unsupported by this bridge. If you're reading this in the future, this has probably become the only remaining way of connecting to WhatsApp, rendering this code somewhat useless.

The rest of the README is archived below, for posterity.



A WhatsApp Web transport for the Extensible Messaging and Presence Protocol (XMPP), otherwise known as Jabber. (alpha!)

This is the spiritual successor of sms-irc, a similar project that works with IRC instead of XMPP.

What is this?

This is a multi-user transport for WhatsApp, using the whatscl library for Common Lisp. By scanning a QR code generated by the bridge with the WhatsApp app on your phone, you can send and receive messages and media with your Jabber ID.

Note: You currently need an XMPP server of your own to try this. Setup instructions assume prosody; the bridge also works on ejabberd, but is not officially supported (though swing by the support MUC and we might be able to provide some pointers, who knows).

What works?

  • Sending private messages/DMs both ways
  • Support for MUCs
  • Magically populating your roster using XEP-0144: Roster Item Exchange
  • Downloading/decrypting media from WhatsApp and uploading it to your XEP-0363 server
  • Avatars
  • Read receipts
  • Status text
  • Typing notifications / chat state
  • XEP-0313: Message Archive Management in MUCs only when enabled in configuration
  • Fetching your entire message history from WhatsApp and making it available via MAM only when enabled in configuration
  • Users joining and leaving MUCs, and the topic changing (partial, requires XMPP-side rejoin)
  • Uploading images to WhatsApp natively

What doesn't yet?

  • Uploading non-image media to WhatsApp (currently, it just comes through as a link)
  • Probably other stuff

What you'll need

  • An XMPP server (we recommend prosody, but it might also work with ejabberd; let us know!)
  • An installation of Docker
    • You can try and run the bridge without Docker. However, we really don't recommend it, especially if you aren't familiar with Common Lisp.
    • Ask in the support MUC (link at the top of this file) if you want to do this.
  • SQLite installed (specifically the sqlite3 command**.


Step 1: configure your XMPP server

Make sure you've followed the links above to set up XEP-0363 and an external component for the bridge. With prosody, your config might look something like:

IMPORTANT: The bridge MUST be allowed to upload things to the XEP-0363 server. For prosody's mod_http_upload, you should configure the http_upload_access option, as shown below. For ejabberd, you'll need to do something with ACLs that I don't quite understand.

Component "upload.capulet.lit" "http_upload"
        http_upload_file_size_limit = 104857600
        http_upload_access = {"whatsapp.capulet.lit"}

Component "whatsapp.capulet.lit"
        component_secret = "juliet"

WARNING: Unless you want to run a public bridge (not recommended at this time), limit access to the external component to only people on your server. (On prosody, add modules_disabled = { "s2s" } to the component configuration.)

Step 2: set up the database and storage for the bridge

I'm going to assume you want to store bridge data at the path /wx. Replace this path with wherever you actually want to put the data in the commands below.

Set up the database schema:

$ sqlite3 /wx/data.sqlite3 < ./schema.sql

Then, configure the bridge -- replacing the values below with the actual values:

$ sqlite3 /wx/data.sqlite3
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> INSERT INTO configuration (rev, server, port, component_name, shared_secret, upload_component_name) VALUES (1, "capulet.lit", 5347, "whatsapp.capulet.lit", "juliet", "upload.capulet.lit");
sqlite> .quit

A few things to note here:

  • The port is whatever port your XMPP server accepts incoming component connections on (not client-to-server or server-to-server connections!). For prosody, the default is 5347.
  • The component_name is whatever you specified in the prosody config for this component.
  • The shared_secret is the same as the component_secret.
  • The upload_component_name is the name of the XEP-0363 HTTP Upload component.

Enabling archiving and full history fetches

If you want to be able to use the MAM and full history fetch features, you'll need to run some additional commands in the above sqlite3 window.

To let users use MAM:

sqlite> UPDATE configuration SET allow_archiving = true;

To let users fetch their WhatsApp history:

sqlite> UPDATE configuration SET allow_history_fetches = true;

WARNING: These options are NOT recommended for people wishing to run a public instance of the bridge. (In fact, if you're doing that, come talk to us in the support MUC first, as there are various things you probably want to be made aware of.)

Note that users must still enable archiving manually via talking to the admin user and executing the enable-archiving command (and similarly for history fetches, which use the full-history-fetch command).

Step 3: run the bridge

You can build the Docker image yourself from the Dockerfile in the repo, or you can just use my hosted copy. (Don't download it a ton you guys, I pay for this stuff.)

You'll want to pass through the directory (/wx, or whatever it is) where you created the database as a Docker volume, so the container can access it. Then, supply the path to the database as the first argument to the container.

The hosted image is called eu.gcr.io/etainfra/whatsxmpp. Using the docker CLI, you might run the bridge like so:

docker run \
    --name whatsxmpp \
    --restart always \
    -v /wx:/data \
    eu.gcr.io/etainfra/whatsxmpp \

Consult the Docker reference for more details on this step, including how to run the image in the background and more!

If you see Connection complete! \o/ in the logs, it's working!

Step 4: set up the WhatsApp Web part

You'll interact with the bridge by talking to admin@whatsapp.capulet.lit (well, the last part of that JID will be different depending on your setup). Send this user help to check that the bridge is working (you should get some help text).

To set it up, have your phone at the ready to scan the QR code (Menu -> WhatsApp Web). Then, send register to the admin user, and scan the QR code you're given.

(Did it break at this part and give you a nasty error? Check your XEP-0363 HTTP Upload service is working correctly, and allows the bridge to use it as described above!)

You should then receive a crapton of presence subscription requests and MUC invites for everyone you are remotely related to on WhatsApp, and for all the WhatsApp groups you're in, and the bridge is done!

Tip: If your client supports XEP-0144: Roster Item Exchange (Gajim on desktop is good for this), send getroster to the admin user to pop up a window where you can insert all your WhatsApp contacts in one go!