HP Printer
HP printers fully local, with sensors that keep their values while the printer sleeps, and scanning to PDF.
Status, ink or toner levels, pages remaining and page counters from the printer's built-in web server, and scanning to PDF, JPEG or PNG from the glass or the feeder, multi-page PDFs included. Built to replace the core HP Printer integration where it is fragile: no unavailable entities when the printer is off, nothing written when nothing changes.
HP Printer has no dashboard of its own: it works on the server, with its entities, actions and notifications described in the documentation below.
Highlights
- Last values kept while the printer is off or asleep, and across a restart; only the status turns off
- Page counters that never go down, for clean long-term statistics
- Tiered polling, ETags and at most two requests at a time, light on the printer
- Status never unknown, paper jams and open doors recognized, cartridge details on each level sensor
- Scan to PDF, JPEG or PNG: glass, feeder or double-sided feeder, resolution, color mode and page size, Scan and add page
- Last scan as a sensor and an image, files downloaded through signed links then deleted
- Zeroconf discovery following address changes, reconfigure, firmware updates, diagnostics
- No Python dependency; 22 languages
Works with
Install
- 1Open the repository in the Marketplace with the Add to Marketplace button above, or add
github.com/juju35/ha-hpas a custom repository (category Integration). - 2Download it from the Marketplace.
- 3Restart Home Assistant and add the integration from Settings → Devices & services.
Documentation
From the README Features
Features
- Never unavailable: a printer that is off keeps every value it last reported (ink levels, counters, network); only the Status turns
offand the Online sensor turns off - Survives restarts: the last values are saved, so after a restart with the printer off the entities come back at once with them, and Home Assistant does not wait for the printer to start
- No false "off": a lost request is tried again before the printer counts as off; a printer already off is not tried twice per poll
- Clean statistics: page counters never go down (a lower value from the firmware is ignored instead of being taken as a reset), and counters and ink are not read while the printer starts up or shuts down, when firmwares report zeros
- Light on the printer: the status is read at every poll (30 s by default), the page counters and ink levels every 5 minutes and right after each job, the network every 30 minutes, the identity every 6 hours and when the printer comes back
- Nothing written when nothing changes: a poll that finds nothing new writes no entity, so the recorder stores nothing
- Unchanged documents not downloaded again: counters, ink, identity and network are asked with their ETag, so an unchanged one costs a short
304and no parsing (the status is always read in full, and cached documents are read in full again every 30 minutes, in case a firmware's ETags do not follow its content) - Unsupported documents not asked again and again: a document the printer does not publish is asked again every 6 hours only
- At most two requests at a time to the printer's small web server
- No dependency: no Python package to install, nothing to conflict with Home Assistant (PNG uses Pillow, which Home Assistant ships)
- Status never unknown: a status this integration does not know is
other, with the printer's own status in an attribute; paper jams and open doors are recognized - Scan to PDF, JPEG or PNG: a Scan button with its settings (format, source, resolution, color mode, page size) and an
hp.scanaction for automations; glass, document feeder and double-sided feeder; multi-page PDFs from the glass with a Scan and add page button; files saved in the local media, the last scan shown by an image and a sensor - Cartridge details on each level sensor: state (
ok,low,very_low…), cartridge number to buy, product number, installed; a cartridge taken out keeps its last level, withinstalled: false - Zeroconf discovery, and a printer announced at a new address is followed there
- Reconfigure the address without removing the printer; a printer that changed address is detected and keeps its values instead of mixing them with another printer's
- Firmware updates shown on the device page
- Diagnostics with the address and serial number redacted
- English, French, German, Spanish, Italian, Dutch, Portuguese (European and Brazilian), Polish, Serbian (Cyrillic and Latin), Romanian, Danish, Swedish, Bulgarian, Russian, Ukrainian, Hungarian, Slovak, Czech, Slovenian, Latvian and Greek
Compared with the core HP Printer integration#
Core hp_printer |
hp (this integration) |
|
|---|---|---|
| Printer off or asleep | Every entity unavailable | Last values kept, status off; Online, Wi-Fi, Ethernet and HP cloud sensors off |
| Restart with the printer off | Setup retried, no entity | Entities at once with their last values |
| Unknown status | unknown |
other + the printer's status in an attribute |
| Requests per poll (every minute) | All documents | Status only; the rest when it can have changed |
| Entity writes per poll | Every entity | None unless a value changed |
| Unchanged documents | Downloaded and parsed again | 304 with ETags |
| Cartridge taken out | Unavailable | Last level kept, installed: false |
| Address change | Remove and add the printer again | Reconfigure, or followed by discovery |
| Scanning | No | PDF (multi-page from the glass too), JPEG or PNG, glass or feeder, buttons and action |
| Python dependency | aiohpprinter |
None |
The two can be installed side by side (different domains), but use only one per printer.
Supported printers
Supported printers
HP printers whose built-in web server publishes the /DevMgmt/*.xml documents: OfficeJet, OfficeJet Pro, ENVY, DeskJet, Smart Tank, LaserJet and Color LaserJet with a network connection. Which sensors are created depends on the model: a printer without a scanner or fax gets no scanner or fax sensor.
To check a printer, open http://<printer address>/DevMgmt/ProductStatusDyn.xml in a browser: it should show an XML document.
Prerequisites
Prerequisites
- Home Assistant 2025.8 or newer
- The printer on the network, with a fixed IP address given in your router (recommended)
Configuration
Configuration
Settings → Devices & services → Add integration → HP Printer, or accept the discovered printer. The printer must be on when it is added.
| Field | Description |
|---|---|
| Host | IP address or hostname of the printer |
| Port | Empty for the default port (80, or 443 with HTTPS) |
| Use HTTPS | Only for printers whose web server answers over HTTPS only |
Options#
| Option | Default | Description |
|---|---|---|
| Status refresh interval | 30 s | How often the status is read (10 to 600 s). Counters and ink levels are read every 5 minutes and after each job, whatever this interval |
| Keep scans not downloaded | 30 min | A scan file not downloaded is deleted after this time (a downloaded file is deleted at once); 0 keeps them |
Entities
Entities
Entities are named after the printer model, for example sensor.hp_officejet_pro_9010_series_black_level. Entity names stay in English in every language, so entity IDs do not depend on the language of Home Assistant.
| Entity | Notes |
|---|---|
sensor.<printer>_status |
ready, processing, copying, scan_processing, cancel_job, in_power_save, initializing, shutting_down, off, tray_empty, paper_jam, close_door_or_cover, other; attributes raw_status, message, alerts |
binary_sensor.<printer>_online |
Whether the printer answered the last poll |
sensor.<printer>_<color>_level |
black, cyan, magenta, yellow, tri_color, in %; attributes state, installed, cartridge, product_number, low_threshold, type |
sensor.<printer>_<color>_pages_remaining |
When the printer estimates it |
sensor.<printer>_<color>_pages_printed |
Disabled by default |
sensor.<printer>_printed_pages, _printed_black_and_white_pages, _printed_color_pages |
Page counters |
sensor.<printer>_scanned_pages, _copied_pages, _faxed_pages |
When the printer has a scanner, copier or fax |
sensor.<printer>_printed_single_sided_sheets, _printed_double_sided_sheets, _scanned_pages_from_document_feeder, _scanned_pages_from_glass, _scanned_double_sided_sheets |
Disabled by default |
sensor.<printer>_paper_jams, _paper_mispicks, _scanner_jams, _scanner_mispicks |
Diagnostic; mispicks and scanner counters disabled by default |
sensor.<printer>_last_seen |
Diagnostic, disabled by default: when the printer last answered (it changes at every poll, so it is the only entity written every 30 s) |
binary_sensor.<printer>_ethernet, _wi_fi, _usb |
Diagnostic: adapter connected (USB disabled by default) |
binary_sensor.<printer>_hp_cloud_registered, _hp_cloud_services |
Diagnostic |
Scanning
Scanning
Printers whose scanner answers eSCL (AirScan, at http://<printer address>/eSCL/ScannerCapabilities) get the scan entities; the choices offered are those the scanner reports.
| Entity | Notes |
|---|---|
button.<printer>_scan |
Scans with the settings below and saves a new file |
button.<printer>_scan_and_add_page |
Scans one more page and adds it to the last PDF: put the next page on the glass and press it, page after page |
select.<printer>_scan_format |
pdf (one file with every page), jpeg or png (one image per page) |
select.<printer>_scan_source |
flatbed (glass), feeder, feeder_duplex |
select.<printer>_scan_resolution |
The resolutions the scanner offers (300 by default) |
select.<printer>_scan_color_mode |
color, grayscale, black_and_white |
select.<printer>_scan_page_size |
a4 (default), letter, legal, max (largest area of the source) |
sensor.<printer>_last_scan |
Time of the last scan; attributes format, files, media_ids (media source IDs, to show the images in the media browser), download_paths (to download the files, PDF included), pages |
image.<printer>_last_scanned_image |
First page of the last scan (PDF, JPEG or PNG) |
Files are saved in the hp folder of the local media (/media/hp on Home Assistant OS), named scan_<date>_<time>.pdf (_1.jpg, _2.jpg… per page in JPEG or PNG); an existing file is never overwritten. They show in Media → Local media → hp. The settings are kept across restarts.
Action hp.scan#
Every field is optional: those not given come from the select entities, and device_id is only needed with several printers.
action: hp.scan
data:
format: pdf # pdf, jpeg, png
source: feeder_duplex # flatbed, feeder, feeder_duplex
resolution: 300
color_mode: grayscale # color, grayscale, black_and_white
page_size: a4 # a4, letter, legal, max
filename: invoice_2026_11
directory: /media/scans # must be in allowlist_external_dirs (the media folders are)
append: false # true: add the pages to the last PDF instead of a new file
response_variable: scan # scan.files, scan.media_ids, scan.download_paths, scan.pages
When a scan is saved, the event hp_scan_completed is fired with device_id, format, files, media_ids, download_paths and pages.
The files of each printer's last scan are downloaded from /api/hp/scans/<entry>/<n> (the paths in download_paths), by a signed-in user or a signed link: Home Assistant's media view only serves audio, video and images, not PDFs. A file is deleted once downloaded (once fully sent: an interrupted download keeps it), and leaves the last scan; a file never downloaded is deleted after 30 minutes (option Keep scans not downloaded; 0 keeps them), even across a restart. Only the files the integration wrote are deleted. ha-printer-card scans from the glass or the feeder and offers the download link.
PDF and PNG are made by the integration from the scanner's JPEG pages (embedded as is in the PDF, no new compression), which is what lets pages be added to a PDF. A scanner that only offers PDF gets its own PDF saved, without adding pages.
Errors are shown, translated, on the button or the action: printer off, scanner busy, feeder empty, a setting the scanner does not offer, folder not allowed.
Automation examples#
Ink running low, whether the printer is on or not:
triggers:
- trigger: numeric_state
entity_id: sensor.office_printer_black_level
below: 10
actions:
- action: notify.mobile_app_phone
data:
message: >
Black cartridge at {{ states('sensor.office_printer_black_level') }} %
({{ state_attr('sensor.office_printer_black_level', 'cartridge') }}).
Scan the feeder to PDF and say where it went:
actions:
- action: hp.scan
data:
source: feeder
format: pdf
response_variable: scan
- action: notify.mobile_app_phone
data:
message: "Scan saved: {{ scan.files | join(', ') }}"
Out of paper:
triggers:
- trigger: state
entity_id: sensor.office_printer_status
to: tray_empty
actions:
- action: notify.mobile_app_phone
data:
message: The printer is out of paper.
How it works
How it works
- Scans: eSCL,
POST /eSCL/ScanJobs(JPEG pages, made into PDF or PNG here) with the settings, thenGET <job>/NextDocumentuntil the printer has no document left; the scanner and feeder states are checked first, a busy answer (503) is asked again, and a job that fails is deleted so the scanner is free. Capabilities are read with the identity, so the scan entities exist even while the printer is off - Documents:
ProductStatusDyn(status),ConsumableConfigDynandProductUsageDyn(cartridges and counters),ProductConfigDyn(identity),/IoMgmt/AdaptersandePrintConfigDyn(network), over HTTP on port 80 (HTTPS optional, self-signed certificates accepted) - A poll reads the status; when it does not answer twice in a row, the printer is off: the status turns
off, the other values stay, and everything is read again when it answers. While it is off, one attempt per poll - Another printer answering at the address (DHCP) is detected by its serial number: this printer counts as off and keeps its values, and the address is checked again every 5 minutes
- The data is saved in
.storage/hp.<entry id>when it changes (and every 10 minutes for the last-seen time while the printer is on), and removed with the printer
Changelog
CHANGELOG.md 1.2.1Nov 12, 2026Latest
Fixes
- While the printer is off or unreachable, the Wi-Fi, Ethernet, USB and HP cloud sensors are off instead of keeping their last value (connected, registered). They show the printer's report again as soon as it answers.
1.2.0Nov 12, 2026
Fixes
- Downloading a PDF scan gave a 14-byte file (
404: Not Found): Home Assistant's media view only serves audio, video and images. The integration now serves the files of each printer's last scan itself, at/api/hp/scans/<entry>/<n>, to a signed-in user or a signed link; their paths are indownload_paths(action response, event, Last scan sensor). Each file is deleted once downloaded (after it is fully sent: an interrupted download keeps it) and leaves the last scan; files never downloaded are deleted after 30 minutes (new option Keep scans not downloaded, 0 keeps them), a restart included. ha-printer-card 2.12.1 downloads through these paths. - The
device_idofhp.scanno longer usesDeviceEntry.config_entries, deprecated since Home Assistant 2026.10.
1.1.1Nov 12, 2026
Maintenance
- Config flow tests no longer set the printer up: the reconfigure test left the image token timer running and failed on the latest Home Assistant depending on test order. No change to the integration itself.
1.1.0Nov 12, 2026
Improvements
- Scans in a media folder get their media source ID (
media_ids) in thehp.scanresponse, thehp_scan_completedevent and the Last scan sensor, which also gives the number ofpages: a dashboard card can show or download the file (ha-printer-card 2.12 does).
Fixes
- The scan folder is checked outside Home Assistant's event loop (the check reads the disk).
1.0.1Nov 12, 2026
Fixes
- Status
other(unknown state on the card) on printers that list several statuses, an informative one first: an OfficeJet Pro 9010 reportsgenuineHP("Cart. HP Instant Ink") beforeready. The status shown is now the most important known one (a stop, then work, then rest), with its message;otheronly when none is known. Alerts are listed once each. - Cartridge states keep acronyms whole:
new_genuine_hpinstead ofnew_genuine_h_p.
1.0.0Nov 12, 2026
First release: a local integration for HP printers, built to replace the core HP Printer integration where it is fragile.
- Sensors keep their last values while the printer is off or asleep, and after a restart with the printer off (saved data): no more unavailable or unknown entities; the Status turns
offand a new Online sensor turns off - Home Assistant starts without waiting for the printer when its data was saved
- A lost status request is tried again before the printer counts as off
- Tiered polling: status every 30 s (option), counters and ink levels every 5 minutes and after each job, network every 30 minutes, identity every 6 hours and when the printer comes back
- ETags: unchanged documents answered with a
304(never for the status; full read every 30 minutes anyway); documents the printer does not publish asked again every 6 hours only; at most two requests at a time - Status
other(with the printer's status in an attribute) instead ofunknown; paper jams and open doors recognized - Cartridge attributes: state, cartridge number, product number, installed, low threshold; a cartridge taken out keeps its last level
- Zeroconf discovery following address changes, reconfigure flow, detection of another printer at the address, firmware updates on the device page, diagnostics
- Nothing written when a poll finds nothing new: no entity write and nothing recorded every 30 s; the Last seen sensor, the one value that changes at every poll, is disabled by default
- Page counters never go down (a lower firmware value is ignored, so long-term statistics see no false reset); counters and ink not read while the printer starts up or shuts down
- Scanning to PDF, JPEG or PNG through eSCL (AirScan): Scan button with format, source (glass, feeder, double-sided feeder), resolution, color mode and page size selects kept across restarts;
hp.scanaction with a response (saved files, pages); files in the local mediahpfolder, never overwritten; Last scan sensor, Last scanned image (first page, PDF included) andhp_scan_completedevent - Multi-page PDFs from the glass: Scan and add page button and
appendfield add the next page to the last PDF; PDFs are built from the scanner's JPEG pages without recompression, PNG converted with Home Assistant's Pillow - No Python dependency