Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save pavelbinar/e14bb47f98768d83828bdee89a47490e to your computer and use it in GitHub Desktop.
Save pavelbinar/e14bb47f98768d83828bdee89a47490e to your computer and use it in GitHub Desktop.

HP LaserJet P1102 Drivers for macOS Sequoia

This instructions provides a solution for installing HP LaserJet P1102 drivers on macOS Sequoia (15.0+). The official HP drivers don't install on the latest macOS versions, but with a simple modification to bypass the operating system version check, you can get your printer working again.

Supported Printer Models

  • HP LaserJet P1102
  • HP LaserJet Pro P1102
  • HP LaserJet Pro P1102w

Manual Installation Steps

  1. Download the official HP Mac Printer Driver
  2. Extract the HewlettPackardPrinterDrivers.pkg file from the HewlettPackardPrinterDrivers.dmg file
  3. From a terminal, navigate to the folder where you extracted the .pkg file and run:
    pkgutil --expand HewlettPackardPrinterDrivers.pkg drivers
    
  4. Open the drivers/Distribution file with any text editor
  5. Change the fragment that says system.version.ProductVersion, '15.0' to system.version.ProductVersion, '16.0'
  6. Save the changes
  7. From the terminal, run:
    pkgutil --flatten drivers HewlettPackardPrinterDrivers-sequoia.pkg
    
  8. Delete the drivers folder, and the HewlettPackardPrinterDrivers.dmg & HewlettPackardPrinterDrivers.pkg files
  9. The file HewlettPackardPrinterDrivers-sequoia.pkg is your new installer that works with macOS Sequoia

Automated Installation

For an automated installation, place the install-driver.sh script in the same directory as your HewlettPackardPrinterDrivers.pkg file and run:

chmod +x install-driver.sh
./install-driver.sh

The script will perform all the necessary modifications and create the compatible installer package.

Notes

  • This solution should work with other HP printer models and installers that have similar version check limitations
  • It may also work with future macOS releases by adjusting the version number accordingly
  • No changes are made to the actual driver files, only to the installer's version check

Disclaimer

This is an unofficial workaround and not officially supported by HP. Use at your own risk.

Credits

This solution is based on the information provided in this blog post by Kartones.

#!/bin/bash
# HP LaserJet P1102 Driver Installer for macOS Sequoia
# Based on: https://blog.kartones.net/post/macos-sequoia-hp-laserjet-p1102-drivers/
# Print colored output
print_green() {
echo -e "\033[0;32m$1\033[0m"
}
print_yellow() {
echo -e "\033[0;33m$1\033[0m"
}
print_red() {
echo -e "\033[0;31m$1\033[0m"
}
# Check if HewlettPackardPrinterDrivers.pkg exists in the current directory
if [ ! -f "HewlettPackardPrinterDrivers.pkg" ]; then
print_red "Error: HewlettPackardPrinterDrivers.pkg not found in the current directory."
print_yellow "Please extract the .pkg file from the HP driver .dmg file first."
exit 1
fi
# Create a temporary directory for the expanded package
print_green "Expanding the HP driver package..."
pkgutil --expand HewlettPackardPrinterDrivers.pkg drivers
# Check if the Distribution file exists
if [ ! -f "drivers/Distribution" ]; then
print_red "Error: Distribution file not found in the expanded package."
exit 1
fi
# Modify the Distribution file to bypass the macOS version check
print_green "Modifying the Distribution file to support macOS Sequoia..."
sed -i '' "s/system.version.ProductVersion, '15.0'/system.version.ProductVersion, '16.0'/g" drivers/Distribution
# Check if the modification was successful
if grep -q "system.version.ProductVersion, '16.0'" drivers/Distribution; then
print_green "Distribution file successfully modified."
else
print_red "Error: Failed to modify the Distribution file."
exit 1
fi
# Create the modified package
print_green "Creating the modified package for macOS Sequoia..."
pkgutil --flatten drivers HewlettPackardPrinterDrivers-sequoia.pkg
# Check if the new package was created
if [ ! -f "HewlettPackardPrinterDrivers-sequoia.pkg" ]; then
print_red "Error: Failed to create the modified package."
exit 1
fi
# Clean up
print_green "Cleaning up temporary files..."
rm -rf drivers
print_green "✅ Installation package successfully created!"
print_green "The modified driver package is: HewlettPackardPrinterDrivers-sequoia.pkg"
print_yellow "You can now install the driver by double-clicking on HewlettPackardPrinterDrivers-sequoia.pkg"
exit 0
@Areko01
Copy link

Areko01 commented Mar 30, 2025

THANKS A LOT BRO <3

@AndriiOpirskyi
Copy link

Thank you man! Helped a lot.

@pavelbinar
Copy link
Author

🫡

@resxton
Copy link

resxton commented May 4, 2025

Thank you!

@luizpicolo
Copy link

Thank you, bro. This helped me a lot.

@TommyClausner
Copy link

Worked on Sequoia 15.5 - thanks a lot !

@knutars
Copy link

knutars commented Jun 24, 2025

This is awesome!
Thank You Very Mouchos!

@gru2007
Copy link

gru2007 commented Jun 27, 2025

Awesome job, dislike for HP devs

@anarnickis
Copy link

Worked on Sequoia 15.5 - thanks a lot !

@fronbasal
Copy link

fronbasal commented Jul 26, 2025

Thank you so much man <3

I had an issue on M1 with the HtmlConfig binary (for setting up WiFi via the printer's web interface) crashing with a kernel panic (bad instruction) after a few site visits. I identified modern browsers (chrome, ff) to be the culprit. A proxy that strips out almost all of the headers etc. fixed this for me. Just run the HtmlConfig (either via plane or via invoking the binary directly - find the args via ps), don't use 127.0.0.1:5050 in the browser, instead run this script and open 127.0.0.1:8080 in your browser:

import socket
import threading
import sys

PROXY_LISTEN_PORT = 8080
TARGET_HOST = "127.0.0.1"
TARGET_PORT = 5050
CRLF = b"\r\n"
HTTP_VERSION = b"HTTP/1.1"


def simplify_http_request(request_data: bytes) -> bytes:
    """
    Simplifies an HTTP request by keeping only the request line, Host, Accept,
    and Accept-Encoding headers. Discards ALL other headers and preserves the body.
    """
    header_end_index = request_data.find(CRLF + CRLF)
    if header_end_index == -1:
        header_part = request_data
        body_part = b""
    else:
        header_part = request_data[:header_end_index]
        body_part = request_data[header_end_index + len(CRLF + CRLF) :]
    lines = header_part.split(CRLF)
    if not lines:
        return b""  # Empty request
    request_line = lines[0]  # e.g., GET /path HTTP/1.1
    simplified_headers = [request_line]
    headers_to_keep = {b"host", b"accept", b"accept-encoding"}
    for line in lines[1:]:
        if (
            not line
        ):  # Should already be handled by header_end_index, but good for robustness
            continue
        try:
            header_name, _ = line.split(b":", 1)
            if header_name.strip().lower() in headers_to_keep:
                simplified_headers.append(line)
        except ValueError:
            pass
    simplified_headers.append(b"")
    return CRLF.join(simplified_headers) + body_part


def handle_client(client_socket):
    """Handles a single client connection."""
    try:
        request_from_browser = client_socket.recv(
            8192
        )  # Increased buffer size for initial read
        if not request_from_browser:
            return
        print(
            f"\n--- Received from Browser ---\n{request_from_browser.decode(errors='ignore')}"
        )
        simplified_request = simplify_http_request(request_from_browser)
        print(
            f"\n--- Simplified Request (to HtmlConfig) ---\n{simplified_request.decode(errors='ignore')}"
        )
        target_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        target_socket.connect((TARGET_HOST, TARGET_PORT))
        print(f"Connected to HtmlConfig proxy at {TARGET_HOST}:{TARGET_PORT}")
        target_socket.sendall(simplified_request)
        while True:
            response_from_target = target_socket.recv(4096)
            if not response_from_target:
                break  # No more data from target
            client_socket.sendall(response_from_target)
    except ConnectionResetError:
        print("Client disconnected unexpectedly.")
    except socket.error as e:
        print(f"Socket error: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    finally:
        client_socket.close()
        if "target_socket" in locals() and target_socket:
            target_socket.close()
        print("Connection closed.")


def start_proxy_server():
    """Starts the main proxy server."""
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(
        socket.SOL_SOCKET, socket.SO_REUSEADDR, 1
    )  # Allow reuse of address
    server_socket.bind(("", PROXY_LISTEN_PORT))
    server_socket.listen(5)  # Max 5 pending connections
    print(f"Python Simple Proxy listening on {PROXY_LISTEN_PORT}")
    print(f"Forwarding requests to {TARGET_HOST}:{TARGET_PORT}")
    try:
        while True:
            client_socket, client_address = server_socket.accept()
            print(f"Accepted connection from {client_address[0]}:{client_address[1]}")
            client_handler = threading.Thread(
                target=handle_client, args=(client_socket,)
            )
            client_handler.daemon = (
                True  # Allow main program to exit even if threads are running
            )
            client_handler.start()
    except KeyboardInterrupt:
        print("\nProxy server shutting down.")
    finally:
        server_socket.close()


if __name__ == "__main__":
    start_proxy_server()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment