Skip to content
Liberated Bread

Liberate Your Wi-Fi Roomba (2024 and Earlier)

Model:
690 / 890 / 960 / 980 / e5 / i3–i8 / j7 / j9 / s9
Written for firmware:
2.x (900-series lineage) and 3.x (i/j/s lineage)
Type:
Software
Difficulty:
2 of 3
Time:
~30 min
HA integration:
roomba

Not yet verified on hardware

Under construction

Most guides here start out this way. This one was researched and reviewed, but it was written from device specifications, vendor documentation and the design of the parts involved rather than from a unit on a bench — so the firmware versions, menu paths, print settings, part fit and timings in it are unconfirmed. Follow it, and check each one against the device in front of you as you go.

Run it on real hardware? Please tell us how it went — that is how a guide gets marked verified, and a correction is every bit as useful as a confirmation. Email support42@liberatedbread.com (the subject line fills itself in), or open an issue if you would rather. Even "followed it, worked, nothing to add" is worth sending.

Check Which Robot You Have First

This guide is for Wi-Fi Roombas from 2024 or earlier. Those run a full local API and this works on them. The 2025 line does not, and no amount of following these steps will change that — so it is worth thirty seconds before reading the rest.

Model Local control
690, 890, 960, 980, e5/e6, i3–i8, j7/j9, s9, Braava jet m6 Yes — this guide applies
Roomba 105, 205, Combo 405 (2025 line) No — local broker removed; connecting to 8883 is refused outright

If you have one of the 2025 models, there is nothing on the robot to talk to. The rest of this page will not help, and it is better to know that now than after an evening of handshakes that cannot succeed. What you can still do is keep it off the internet — the firewall guide works on any device — but you will lose the vendor app along with the cloud, because on those models the app IS the cloud.

What You're Liberating From

Older Wi-Fi Roombas already run a full local API. It's an MQTT broker, on the robot, on TCP 8883 — the same channel the iRobot app uses when the phone is on the same Wi-Fi. It needs no account, no internet, and no permission. It has been there since the 980.

So on those robots there's nothing to fix. What there is, is something to protect.

iRobot filed Chapter 11 in December 2025 and was bought by Picea Robotics in January 2026. More to the point: the 2025 model line ships with the local broker removed. That is the direction of travel, and the delivery mechanism for applying it to a robot that still has one is a firmware update.

That is what makes this worth doing now rather than eventually. An older robot has something the new ones don't, and it keeps it only until it is updated. This guide gets the credentials off the robot, gets the robot off the internet, and connects it to Home Assistant — in that order, for a reason.

This is dorita980's work. koalazak reverse-engineered every part of what follows: the discovery probe, the password handshake, the command vocabulary. pschmitt/roombapy carried it into Python and is what Home Assistant actually runs. We wrote a guide around their work; they did the work.

Prerequisites

Step 1: Get the Password First

Do this before you touch the firewall. One of the two routes below goes through iRobot's servers, and if you block the robot first you'll be temporarily unblocking it to finish this step. The other route is entirely local, but it doesn't work on every robot, so you may end up needing the first one anyway.

You are collecting two values:

Write both down. The password only changes on a factory reset, and it's what Home Assistant, dorita980, and everything else will ask you for. The Liberated Bread app shows you a screen built for exactly this — screenshot it.

Route A: the HOME button (no account)

Works offline, needs nothing from iRobot.

  1. Put the robot on its dock, powered on.
  2. Close the iRobot app on every phone in the house. The robot serves one client at a time and the app will hold the slot.
  3. Hold the HOME button for about two seconds, until the robot plays a series of tones. Release.
  4. Immediately, on a computer on the same network:
npm install -g dorita980
get-roomba-password <robot-ip>

It prints the BLID and the password. In the Liberated Bread app, this is the "Hold the HOME button" path in the Roomba adoption wizard — same handshake, same result, and it retries for you.

If it fails, re-hold the button and try again before assuming it can't work. j-series firmware is known to drop the first attempt or two.

Route B: your iRobot account (extraction only)

If the button route won't complete, log in once and read the same values out of iRobot's API:

get-roomba-password-cloud <your-irobot-email> <your-irobot-password>

This returns every robot on the account with its BLID and password. That is all it's for — nothing about controlling the robot afterwards needs an account, and the credentials are identical to what Route A would have given you. The Liberated Bread app offers this too, and never stores your iRobot account password; it uses it for the one login call and throws it away.

Once you have the credentials, you never need the account again. Which is convenient, because in the next step you're going to make it unreachable.

Step 2: Lock It Down

Now block the robot from the internet.

The full how-to, for UniFi, MikroTik, OPNsense/pfSense, OpenWrt, Firewalla and consumer routers, is on Keep It Off the Internet. The short version:

  1. Give the robot a fixed IP (a DHCP reservation is fine).
  2. Add a firewall rule blocking that IP from the WAN, leaving LAN traffic alone.

What keeps working: everything in this guide. Local MQTT on 8883, discovery on UDP 5678, all your commands and all your sensors.

What stops: the iRobot app from outside your house (it still works on your Wi-Fi), cloud-stored schedules, map sync on the i/j/s series, and firmware updates. That last one is the entire point.

Don't try to block only the update server. Vendors move update traffic between hosts without announcing it, and a blocklist that's one host short is a firmware update that arrives anyway. Block outbound wholesale.

Step 3: Adopt It Locally

One thing should hold the robot. It accepts a single local connection at a time, and a new one evicts the old. Two things talking to it directly means both take turns being locked out — including your own iRobot app. So pick one owner and let everything else go through it. That is the thread running through this whole section.

Home Assistant — start here

If you run Home Assistant, this is the answer, and it stays the answer even if you also want the phone app.

Settings → Devices & Services → Add Integration → iRobot Roomba and Braava. It asks for the host, the BLID and the password from Step 1. That's it — Home Assistant's roomba integration is local_polling, so it talks to the robot and nothing else.

You get a vacuum entity (start, pause, stop, return to base, locate), plus battery and status sensors.

Three reasons to make it the owner rather than one option among several:

Liberated Bread app

Open the Wi-Fi tab and scan. The robot answers a broadcast probe on UDP 5678, so it shows up by name without you typing an address. Tap it, run through the adoption wizard, and the credentials go into your phone's keychain — not into preferences, not into a file.

If you already have Home Assistant, point the app at it instead — on a robot's screen, choose "How to reach this robot" and pick the Home Assistant entity. You get the same panel, the same buttons and the same readings, but the commands travel to HA and HA talks to the robot. Two things worth knowing:

Straight-at-the-robot is the right choice when the app is the only thing driving it. If anything else is, or might be, put that other thing in front.

Command line

get-roomba-password above works straight from a global install — npm links its binary onto your PATH. Using dorita980 as a library is different: require does not look in npm's global directory, so the snippet below sets NODE_PATH to it rather than making you install the package a second time.

# One-off, using dorita980 directly
BLID=<blid> PASSWORD=<password> ROBOT_IP=<ip> \
NODE_PATH="$(npm root -g)" \
  node -e "
    const d = require('dorita980');
    const r = new d.Local(process.env.BLID, process.env.PASSWORD, process.env.ROBOT_IP);
    r.on('connect', () => r.clean().then(() => r.end()));
  "

One client at a time. The robot accepts a single local connection and a new one evicts the old. If the iRobot app stops working on your Wi-Fi the moment Home Assistant connects, that's why — and it's why anything long-running should connect, act, and disconnect rather than hold the socket open.

Or: put rest980 in front of it

rest980 is koalazak's own HTTP wrapper around dorita980 — same author as the protocol. It holds the robot connection and answers plain HTTP, so everything else talks to it instead of fighting over the robot:

docker run -p 3000:3000 \
  -e BLID=<blid> -e PASSWORD='<password>' -e ROBOT_IP=<ip> \
  koalazak/rest980

Then GET /api/local/action/start, /dock, /pause, and /api/local/info/state. The Liberated Bread app can be pointed at a rest980 address per robot instead of talking to the robot directly.

This is worth doing in two cases:

One gap worth knowing: rest980 publishes no endpoint for locate, so the "make it beep" button isn't available in that mode. Everything else is.

Step 4: Verify

The real test: unplug your internet. Not the router — the WAN.

  1. With the internet down, send the robot a clean command from Home Assistant or the app. It should go.
  2. Send it home. It should dock.
  3. Check the battery sensor still updates.

Then plug the internet back in and confirm your firewall rule is actually doing something — your router's firewall log should show blocked connection attempts from the robot's IP. If it shows nothing at all, the rule may be matching the wrong thing.

Troubleshooting

get-roomba-password returns nothing, or an error

The robot wasn't in disclosure mode. Re-hold HOME until you hear the tones — about two seconds, and the tone is the confirmation, not the clock. Make sure the robot is on the dock and no phone has the iRobot app open.

If it fails repeatedly on a j7 or j9, keep trying: that firmware resets the first connection or two before answering. If it never works, use Route B.

The password handshake fails before it starts, with a TLS error

Older robot firmware only offers a TLS cipher (AES128-SHA256) that modern TLS libraries have retired. Node.js hits this too, which is why dorita980 ships the ROBOT_CIPHERS and ROBOT_TLS_LEGACY environment variables:

ROBOT_TLS_LEGACY=1 ROBOT_CIPHERS=AES128-SHA256 get-roomba-password <robot-ip>

The Liberated Bread app cannot work around this directly — the phone TLS stack it uses doesn't offer that cipher and gives no way to ask for it. If the app tells you the robot needs a legacy cipher, that's honest, not a bug. Two things do work:

Home Assistant connects, then drops

Something else took the connection slot. Close the iRobot app, and check you don't have a second integration or a rest980 container pointed at the same robot.

The robot vanished from discovery after I set up VLANs

Discovery is a UDP broadcast on port 5678, and broadcast doesn't cross VLANs. Enabling mDNS reflection doesn't help — that's a different protocol. Either keep whatever is controlling the robot on the same VLAN, or skip discovery and configure it by its fixed IP, which works fine.

It worked, then stopped after a factory reset

A factory reset mints a new password. Go back to Step 1.

Going Further

Protocol Reference


Written against firmware 2.x and 3.x and Home Assistant 2026.7, from koalazak/dorita980 and pschmitt/roombapy — the projects that worked this protocol out. Not yet run end to end on a robot by us.

Protocol reference: Device spec Protocol docs — liberatedbread-protocol-specs
Heads up: These guides are for hardware you own. Use common sense. Don't do anything illegal. Pigs Can Fly Labs LLC isn't responsible for bricked devices, voided warranties, or angry IoT cloud providers. If you're not sure about something, ask someone who knows.