Automated batch printing for Konica Minolta printers running AccurioPro ProfiWEB (Print Manager). Import .icjx job files and print them with all embedded settings preserved — duplex, paper profile, image shift, booklet layout, and more.
Also supports direct PDF printing via IPP.
Zero dependencies — uses only Python 3 standard library + system curl.
Tested on:
- AccurioPrint 2100 (B&W) with ProfiWEB 1.0PW-4030
- AccurioPrint C4065 (Color) with ProfiWEB 6.0PWRW-1238
Should work with any Konica Minolta printer running AccurioPro Print Manager / ProfiWEB, including:
- AccurioPrint 2100, C4065
- AccurioPress C759 / C754e / C654e
- Other models with the ProfiWEB web interface (port 30083)
# Clone the repo
git clone https://github.com/bulgariamitko/profiweb-auto-print.git
cd profiweb-auto-print
# Print an .icjx file (imports via ProfiWEB, preserves all settings)
python3 auto_print.py --printer 10.0.0.50 order.icjx
# Batch print all .icjx files in a folder
python3 auto_print.py --printer 10.0.0.50 /path/to/orders/*.icjx
# Check what paper is loaded in each tray
python3 auto_print.py --printer 10.0.0.50 --trays
# Print only if 150g paper is loaded
python3 auto_print.py --printer 10.0.0.50 --paper-weight 150 order.icjx
# Print a PDF directly via IPP
python3 auto_print.py --printer 10.0.0.50 document.pdf
# Preview what would happen (no actual printing)
python3 auto_print.py --printer 10.0.0.50 --dry-run *.icjxThese are Konica Minolta's factory default admin passwords. You'll need these for admin operations via checkAdminPwd.fcgi. Operator login (sessionLogin.fcgi) does not require a password.
| Model | Default Admin Password |
|---|---|
| AccurioPrint 2100, C754e | 12345678 |
| AccurioPress C654e, C759 | 1234567812345678 |
Note: These are well-known factory defaults. Change them in production if security is a concern.
.icjx files are Konica Minolta's proprietary job export format. They contain a PDF plus all print settings (duplex, paper size, paper profile, image shift, N-up, finishing, etc.).
The script:
- Registers a session with ProfiWEB (
register.fcgi) - Logs in as Operator (
sessionLogin.fcgi) - Imports the .icjx file via
jobRestore.fcgi— this preserves ALL embedded settings - Finds the imported job in the Hold queue (
jobList.fcgi) - Locks the job (
jobLock.fcgi) - Prints and unlocks (
jobPrintAndUnlock.fcgi)
PDFs are sent directly via the Internet Printing Protocol (IPP) on port 631. This is simpler but supports fewer settings (duplex, N-up, but no paper profiles or image shift).
python3 auto_print.py [OPTIONS] FILE [FILE ...]
| Option | Description | Default |
|---|---|---|
--printer IP |
Printer IP address (required) | — |
--trays |
Show paper loaded in each tray and exit | — |
--paper-weight N |
Required paper weight (g/m²). Aborts if no tray matches | — |
--mode {profiweb,ipp} |
Print mode | profiweb for .icjx, ipp for .pdf |
--copies N |
Number of copies (ProfiWEB mode) | 1 |
--no-delete |
Keep job in queue after printing (ProfiWEB) | Delete after print |
--duplex |
Force duplex printing (IPP mode) | Single-sided |
--profiweb-port PORT |
ProfiWEB port | 30083 |
--ipp-port PORT |
IPP port | 631 |
--dry-run |
Preview without printing | Off |
# Print a single .icjx with all embedded settings
python3 auto_print.py --printer 10.0.0.50 order.icjx
# Print 3 copies
python3 auto_print.py --printer 10.0.0.50 --copies 3 order.icjx
# Keep job in queue after printing (don't delete)
python3 auto_print.py --printer 10.0.0.50 --no-delete order.icjx
# Batch print all .icjx files
python3 auto_print.py --printer 10.0.0.50 /path/to/folder/*.icjx
# Print PDF via IPP with duplex
python3 auto_print.py --printer 10.0.0.50 --duplex document.pdf
# Force PDF through ProfiWEB instead of IPP
python3 auto_print.py --printer 10.0.0.50 --mode profiweb document.pdf
# Dry run — see what would happen
python3 auto_print.py --printer 10.0.0.50 --dry-run *.icjx.icjx is Konica Minolta's job export format created by the "Export" button in ProfiWEB. Structure:
[outer tar archive]
└── ./1 {filename}.pdf (NOT a raw PDF)
├── [~41KB binary header] (job metadata, printer IP, settings refs)
│ ├── Bytes 0-3: 0xFFFFFFFF (magic)
│ ├── Job name (repeated)
│ └── Source printer IP
├── [gzip stream] (starts at ~offset 41056, magic: 0x1F8B)
│ └── [inner tar]
│ ├── {id}.pre (THE ACTUAL PDF — starts with %PDF-)
│ ├── EngPage000.dbm (engine settings — binary)
│ ├── bppage000.dbm (box print settings — binary)
│ ├── Adjustment/ (empty)
│ ├── ToneCurve/ (empty)
│ └── thumb/ (page thumbnails as .thm)
The script can also extract the PDF from .icjx files for IPP printing (use --mode ipp), though this loses the embedded print settings.
See PROFIWEB_API_REFERENCE.md for the complete API documentation, including:
- All 80+
.fcgiendpoints discovered from bundle.js analysis - Authentication flow (register, login, admin)
- Job management (upload, import, lock, print, delete)
- Complete list of 216 print features (printFeatures)
- Container/queue system (Active, Hold, HDD, Secure, History)
- Device information and status polling
- Hot folder configuration
- IPP printing details
- Curl examples for every operation
- Known issues and workarounds
| Endpoint | Method | What It Does |
|---|---|---|
register.fcgi |
GET | Create a session |
sessionLogin.fcgi |
POST | Login as Operator (no password) |
checkAdminPwd.fcgi |
POST | Admin login (password required) |
jobSubmit.fcgi |
POST (multipart) | Upload PDF to queue |
jobRestore.fcgi |
POST (multipart) | Import .icjx file (preserves settings) |
jobList.fcgi |
GET | List jobs in a container |
jobDetails.fcgi |
GET | Get full job details + print settings |
jobLock.fcgi |
POST | Lock/unlock a job |
jobPrintAndUnlock.fcgi |
POST | Print a locked job |
setJobDetailsAndUnlock.fcgi |
POST | Modify settings and print |
jobDelete.fcgi |
POST | Delete a job |
deviceInfo.fcgi |
GET | Get printer status (trays, toner, etc.) |
productionData.fcgi |
GET | Get current print production status |
hotFolderList.fcgi |
GET | List hot folders |
# Register a session
curl -s "http://PRINTER:30083/register.fcgi?sessionId=-1&viewId=-1&ts=$(date +%s)000"
# Returns: {"sessionId": "abc123...", "viewId": 0}
# Login as Operator
curl -s -X POST "http://PRINTER:30083/sessionLogin.fcgi" \
--data-urlencode "notauthuser=Operator" \
--data-urlencode "sessionId=YOUR_SESSION" \
-d "viewId=0&ts=$(date +%s)000"
# Import an .icjx file
curl -s -X POST "http://PRINTER:30083/jobRestore.fcgi" \
-F "file=@job.icjx;type=application/octet-stream" \
--form-string "sessionId=YOUR_SESSION" \
-F "viewId=0"
# Upload a PDF to Hold queue
curl -s -X POST "http://PRINTER:30083/jobSubmit.fcgi" \
-F "file=@document.pdf;filename=document.pdf" \
--form-string "sessionId=YOUR_SESSION" \
-F "viewId=0" -F "containerId=268435441" -F "hold=true"
# List jobs in Hold queue
curl -s "http://PRINTER:30083/jobList.fcgi?containerId=268435441&viewId=0"
# Lock a job
curl -s -X POST "http://PRINTER:30083/jobLock.fcgi" \
-d "action=lock&jobId=JOB_ID&containerId=268435441&viewId=0&ts=$(date +%s)000" \
--data-urlencode "sessionId=YOUR_SESSION"
# Print a locked job (and delete it after)
curl -s -X POST "http://PRINTER:30083/jobPrintAndUnlock.fcgi" \
-d "jobId=JOB_ID&containerId=268435441&printMode=Print&deleteJob=true&numOfCopies=1&isLocked=true&viewId=0&ts=$(date +%s)000" \
--data-urlencode "sessionId=YOUR_SESSION"
# Get printer status
curl -s "http://PRINTER:30083/deviceInfo.fcgi?viewId=0"
# Check what's currently printing
curl -s "http://PRINTER:30083/productionData.fcgi?viewId=0"ProfiWEB organizes jobs into containers (queues):
| Container | ID | Description |
|---|---|---|
| Active | 268435440 | Currently printing |
| Hold | 268435441 | Waiting to print |
| HDD | 268369922 | Stored on hard drive |
| Secure | 268435443 | Password-protected |
| History | 268435444 | Completed jobs |
| Editable Active | 268435445 | Active but editable |
When a job is imported via .icjx, all 216 print features are preserved. Key settings:
| Feature | Values | Description |
|---|---|---|
NumCopies |
1-9999 | Number of copies |
Duplex |
True / False |
Two-sided printing |
PageSize |
A3, A4, A5, etc. |
Document size |
TargetPaperSize |
Auto, A3, A4, etc. |
Output paper size |
InputSlot |
Auto, Tray1, Tray2 |
Paper tray |
Orientation |
Port / Land |
Portrait/Landscape |
Layout |
None, 2up, 4up |
N-up layout |
FullBleed |
True / False |
Full bleed printing |
Fold |
None, HalfFold, etc. |
Folding |
Staple |
None, etc. |
Stapling |
Resolution |
1200dpi |
Print resolution |
HorizontalShift |
integer (micrometers) | X image shift |
VerticalShift |
integer (micrometers) | Y image shift |
ScaleToFit |
True / False |
Scale to fit |
Binding |
Left, Right, Top |
Binding edge |
Full list of all 216 features available in PROFIWEB_API_REFERENCE.md.
| Method | Port | Settings Support | Complexity |
|---|---|---|---|
| ProfiWEB + .icjx | 30083 | ALL settings preserved | Medium |
| IPP | 631 | Duplex, N-up, basic | Simple |
| Hot Folder | SMB/FTP | Hot folder defaults | Simple |
| Raw/JetDirect | 9100 | Printer defaults only | Simplest |
| LPR | 515 | Basic | Simple |
# Via lp command
lp -h PRINTER:631 -d ipp document.pdf
# With duplex
lp -h PRINTER:631 -d ipp -o sides=two-sided-long-edge document.pdfcat document.pdf | nc PRINTER 9100| Port | Protocol | Description |
|---|---|---|
| 631 | IPP | Internet Printing Protocol |
| 515 | LPR | Line Printer Remote |
| 9100 | RAW | JetDirect direct printing |
| 445 | SMB | File sharing (hot folders) |
| 139 | NetBIOS | Name service |
| 21 | FTP | File transfer |
| 30083 | HTTP | ProfiWEB web interface |
Python's http.client has a subtle incompatibility with the ProfiWEB server — jobPrintAndUnlock.fcgi returns AioJobInUse even after a successful lock with the same session. The identical request works via curl. The auto_print.py script uses subprocess with curl as a workaround.
Previously believed to be browser-only — now confirmed fully scriptable (2026-05-27). The catch is that the same session must hold a jobLock.fcgi lock on the job before calling it; with the lock, the server accepts the raw jobDetails.fcgi response back as jobData= (mutate only the fields you care about). Without the lock you get a generic "Print Manager is disconnected" error that was easy to misdiagnose.
Gotcha: jobData is a 25 KB JSON blob containing &, =, ", {, }. Use curl --data-urlencode key=value for every parameter (each value encoded independently), or the server's form parser truncates jobData at the first stray character and returns InvalidParameter: jobData is empty.
This is what enables per-job tray selection, paper-profile selection, and weight enforcement from auto_print.py. See PROFIWEB_API_REFERENCE.md for the full recipe.
Common default admin passwords by model:
| Model | Password |
|---|---|
| AccurioPrint 2100, C754e | 12345678 |
| C654e, C759 | 1234567812345678 |
- Python 3.6+
curl(system command — preinstalled on macOS/Linux)- Network access to the printer's ProfiWEB interface (port 30083)
The ProfiWEB API is undocumented. All endpoints were discovered by:
- Analyzing the minified
bundle.js(3.8MB AngularJS 1.8.2 app) served by ProfiWEB - Intercepting browser network requests via Chrome DevTools
- Testing endpoints with curl to determine parameters and behavior
- Examining the
fcgiSrvAngularJS service that wraps all API calls
The PROFIWEB_API_REFERENCE.md documents everything found, including the 80+ endpoints, request formats, response structures, and container system.
Found additional endpoints or settings? PRs welcome. If you have a different Konica Minolta model, testing and reporting compatibility would be valuable.
MIT