Cash Drawer Kick: the ESC/POS Command
How cash drawers really open — the ESC p pulse through the printer's RJ12 port — with the exact bytes, pin timings, and fixes when the drawer won't kick.
Published 2026-07-24 · Updated 2026-08-02 · For developers →
A cash drawer doesn't open on its own — the receipt printer opens it. The drawer plugs into the printer's RJ12 socket (usually labeled "DK" for drawer kick), and the POS sends the printer a five-byte ESC/POS command (ESC/POS is the byte language receipt printers speak) — ESC p m t1 t2, typically 1B 70 00 19 FA — that fires a short electrical pulse down that cable to release the drawer's latch. If your drawer won't open, the fault is in that chain: the command, the printer, the cable, or the drawer. This guide covers the exact bytes, the troubleshooting flow, and a measured case study of the strangest failure mode of all — a kick that fires correctly, 9 to 24 seconds late.
Why the drawer plugs into the printer
Cash drawers are electrically dumb: inside is a spring-loaded latch held by a solenoid (an electromagnet). Energize the solenoid for a fraction of a second and the latch releases — that's the entire interface. Rather than give every drawer its own network connection, POS hardware standardized on borrowing the printer's: receipt printers carry a drawer-kick port (an RJ12 socket that looks like a slightly wider phone jack, often labeled DK), and a dedicated kick cable runs from there to the drawer.
This has a practical consequence worth knowing before any troubleshooting: no working printer, no opening drawer. If the printer is off, offline, or erroring, drawer commands go nowhere.
Two jacks that look identical
On many printers and drawers, an RJ12 kick cable will physically seat in an RJ45 network jack, and some drawers have a second port for daisy-chaining. Plugging the kick cable into the wrong socket is one of the most common "drawer is dead" causes — and at worst can damage a network port. Find the label: DK on the printer, and the port marked for the printer (not the pass-through) on the drawer.
The command: ESC p m t1 t2
The ESC/POS command "generate pulse" is five bytes:
| Byte | Meaning |
|---|---|
1B | ESC |
70 | p — generate pulse |
m | Which connector pin to pulse: 00 = pin 2 (drawer 1), 01 = pin 5 (drawer 2) |
t1 | Pulse ON time = t1 × 2 milliseconds |
t2 | Pulse OFF time = t2 × 2 milliseconds |
The near-universal default is:
1B 70 00 19 FAThat's m = 0 (pin 2, the first drawer), t1 = 0x19 (25 × 2 = 50 ms on), t2 = 0xFA (250 × 2 = 500 ms off). Fifty milliseconds of current is enough for virtually every solenoid; the off-time mostly matters as a spacing guard if you fire twice.
Sending it from code is one raw write. To a network printer on port 9100:
import net from "node:net";
const KICK = Buffer.from([0x1b, 0x70, 0x00, 0x19, 0xfa]);
const sock = net.createConnection(9100, "192.168.1.240", () => {
sock.end(KICK);
});Two variants you'll meet in the wild:
DLE DC4 fn=1(10 14 01 m t) is the "real-time" cousin — some printers process it even mid-job. Support varies;ESC pis the portable choice.- "Open drawer before/after printing" checkboxes in POS software just prepend or append these same bytes to the receipt job.
Pins and pulses, briefly
The RJ12 connector carries six pins: pin 2 and pin 5 are the two kick signals (that's what m selects), pin 4 carries the drive voltage (usually 24 V from the printer's own supply), and pin 3 can carry a drawer open/closed switch signal back to the printer — more on that below. Two-drawer setups (rare outside banks and some bars) use a splitter or a dual-drawer cable, with one drawer on pin 2 and the other on pin 5.
If a drawer clicks but doesn't pop open, the solenoid is firing but the pulse may be too short for that drawer's mechanism, or the drawer is physically jammed (overstuffed bill slot is the classic). Try a longer pulse — t1 = 0x32 gives 100 ms:
1B 70 00 32 FATroubleshooting: drawer won't open
Work down this list in order; each step isolates one link in the chain.
- Does the drawer open with the key? Turn the manual key/release. If it won't open even manually, the drawer is jammed or broken — no command will fix it.
- Is the printer online? Print a test receipt from the POS. If the receipt doesn't print, fix the printer first (paper, cover, power, network — see our kitchen printer setup guide for the network side). The drawer command rides through the printer.
- Check the cable and ports. Kick cable firmly seated in the printer's DK jack (not the network jack, not a phone-line jack) and in the drawer's printer port (not the daisy-chain port)? Kick cables are not ordinary phone cables — the wiring differs by drawer brand, so use the cable that came with the drawer or a replacement specified for that drawer/printer pairing.
- Try the other pin. If the software fires
m = 0(pin 2) and nothing happens, trym = 1(1B 70 01 19 FA). Some cables and drawers wire the kick line to pin 5 instead. POS settings often expose this as "drawer 1 / drawer 2." - Lengthen the pulse. Solenoid clicks but no pop: raise
t1from19to32(50 → 100 ms) as shown above. - Swap components to isolate. Another kick cable, then another drawer, then another printer if available. In practice the cable is the culprit far more often than the drawer.
- Confirm the software sends the command at all. Many POS systems only kick the drawer on cash-tender transactions, not card payments — by design. Check for a "no sale" / "open drawer" button and the drawer-kick settings before assuming hardware failure.
A worked example: the drawer that opened 9 seconds late
There's a failure mode the checklist above can't catch, because nothing in the chain is broken: the kick fires every time — just late. We hit it ourselves on the Proxy Nodes bench, and it's worth walking through because the debugging method transfers to any networked kick path.
The symptom: a drawer-kick request that should feel instant took anywhere from 9 to 24 seconds. Not failing, not intermittent — reliably slow, with the delay landing at oddly consistent values. Every instinct points at the pulse: maybe t1 is wrong, maybe the solenoid is weak. But pulse parameters decide whether the drawer opens, not when. The 50 ms pulse was fine.
The productive move is to split the path and time each segment. A networked drawer kick has two phases: establish the TCP connection, then write five bytes. Timing them separately showed the write completing in single-digit milliseconds — once the connection existed. All of the 9–24 seconds lived in the TCP connect.
That pattern has a fingerprint. When a device's Wi-Fi radio is in power-save mode, it sleeps between access-point beacons and can miss packets sent to it — including the SYN packet that opens a TCP connection. The client's operating system doesn't give up; it retransmits the SYN on an exponential backoff (roughly 1 s, then 2 s, then 4 s, then 8 s...). So the connect succeeds eventually, on whichever retry catches the radio awake — and the observed latency quantizes near the retry marks instead of varying smoothly. Delays that cluster at specific values are the tell that you're watching a retransmission schedule, not a slow wire.
The fix was firmware, not hardware: firmware 1.0.9 disabled Wi-Fi power save on the node, and the measured request-to-pulse time dropped from 9–24 s to 0.15 s. The lesson generalizes: when a networked peripheral "works but is slow," measure the connection setup before touching the payload. The bytes are almost never the slow part.
Checking drawer status with DLE EOT
ESC/POS can also ask whether the drawer is open. The real-time status command DLE EOT n with n = 1 requests printer status:
10 04 01The printer replies with one status byte; bit 2 reflects the level on drawer-kick pin 3, which — when the drawer has a status switch wired to that pin — tells you open versus closed.
The honest caveat: many setups can't actually report drawer state. Plenty of cash drawers don't wire a status switch to pin 3 at all, plenty of kick cables don't carry the pin, and even when both do, whether "high" means open or closed varies by drawer. The printer dutifully reports a pin level either way, which is how you get systems confidently displaying "drawer closed" while the till sits wide open. If drawer-open alerts matter to your operation, test the reading with your exact drawer, cable, and printer — and treat an unverifiable reading as unknown, not closed. (Byte-level detail on all four status queries lives in our DLE EOT status guide.)
One HTTP request instead of a raw socket
This is why drawer support in Proxy Nodes works the way it does. A node sits in front of the printer and serves a plain HTTP endpoint on your local network, so opening the drawer is one request instead of a raw-byte socket write:
curl -X POST http://proxynodes-a1b2.local/drawer/kickThat endpoint ships in firmware 1.0.24, and the whole path is measured: 0.15 s from request to kick pulse. The status side is deliberately honest — when drawer state genuinely can't be verified through the hardware (no switch, no pin 3 in the cable), the driver layer models the reading as unknown rather than guessing, so your UI can say "can't tell" instead of showing a green checkmark over an open till. And the node accepts the classic raw bytes on port :9100 — ESC p, DLE EOT, the lot — so existing POS software needs zero changes. Developers can exercise the entire flow, drawer kick included, against the free digital twin before any hardware is involved; the same 123 conformance specs run against the twin and a real node.
Quick reference
| Task | Bytes |
|---|---|
| Kick drawer 1 (pin 2), 50 ms | 1B 70 00 19 FA |
| Kick drawer 2 (pin 5), 50 ms | 1B 70 01 19 FA |
| Longer 100 ms pulse (stubborn drawers) | 1B 70 00 32 FA |
| Real-time kick variant | 10 14 01 00 01 |
| Query printer status (bit 2 = drawer pin 3) | 10 04 01 |
For the rest of the command set, see the ESC/POS command reference. Operators wiring up a full station will also want the kitchen printer setup guide and the hub pages for restaurants and developers.
FAQ
Frequently asked questions
- What is the ESC/POS command to open a cash drawer?
- ESC p m t1 t2 — five bytes, typically 1B 70 00 19 FA. The third byte selects the connector pin (00 for drawer 1 on pin 2, 01 for drawer 2 on pin 5), and the last two set the pulse on and off times in units of 2 milliseconds, so 19 hex gives a 50 ms pulse.
- Why does the cash drawer connect to the receipt printer?
- The drawer is just a solenoid latch that needs a brief electrical pulse. Printers standardized on providing that pulse through an RJ12 drawer-kick port, so the drawer borrows the printer's connection to the POS instead of needing its own. It also means the drawer cannot open if the printer is off or offline.
- Why does my cash drawer click but not open?
- The solenoid is firing but the latch is not releasing. Usually the pulse is too short for that drawer mechanism — raise t1, for example 1B 70 00 32 FA for 100 ms — or the drawer is physically jammed, most often by an overstuffed bill slot pressing against the latch.
- Why does my cash drawer open several seconds late?
- If the drawer opens reliably but slowly, the pulse is fine — measure the network path instead. Time the TCP connect separately from the byte write: a delay that clusters near 1, 3, 7, or 15 seconds is the client retransmitting SYN packets to a device whose Wi-Fi radio is sleeping in power-save mode. We hit exactly this — 9 to 24 second kicks — and disabling power save in firmware 1.0.9 brought it to a measured 0.15 s.
- Can I use a regular phone cable as a drawer kick cable?
- No. Kick cables use the same RJ12 connector as phone cables but are wired differently, and the wiring varies between drawer brands. Use the cable supplied with the drawer or a replacement specified for your exact drawer and printer combination.
- Can software detect whether the drawer is open?
- Sometimes. The DLE EOT status query (10 04 01) returns a byte whose bit 2 reflects drawer-kick pin 3, but that only means something if the drawer has a status switch wired to that pin and the cable carries it — many do not, and polarity varies by drawer. Test with your exact hardware before trusting drawer-open alerts, and treat an unverifiable reading as unknown, not closed.
Related reading
- ESC/POS Commands: a Practical ReferenceThe ESC/POS commands that matter in production — init, text style, feed, cut, drawer kick, status — with raw bytes and the quirks between brands.
- ESC/POS Printer Status: DLE EOT ExplainedThe DLE EOT real-time status commands byte by byte — paper, cover, drawer, errors — plus why many printers lie or stay silent, and what to do about it.
- Kitchen Printer Setup: a No-Nonsense GuideSetting up a restaurant kitchen printer: thermal vs impact, Ethernet vs Wi-Fi, static IPs, routing by station, and surviving printer swaps.