A lightweight desktop HTTP client built with Python and PyQt5.
I wanted a simple tool to send and inspect HTTP requests without installing the Electron-based Postman client. After installation, Postman easily takes up ~500 MB on disk. HTTP Requester keeps the workflow familiar while staying small, fast to launch.
- Python 3.8+
- PyQt5
- requests
pip install -r requirements.txt
python main.pyPortable builds bundle a self-contained Python runtime and dependencies, so you can extract the archive and run the app without installing Python or running pip on your system. Both use a small native launcher that reads a config file next to the executable and starts the embedded Python entry point.
Each release includes a portable HttpRequester-{version}-Win7-amd64.7z ~18 MB 7z archive for Windows 7 and later with Python 3.11. Extract and run HttpRequester.exe. The launcher source is PythonCaller (Windows).
HttpRequester/
├── HttpRequester.exe
├── HttpRequester.exe.conf → RuntimeX64 + Lib\http-requester\main.pyc
├── RuntimeX64/ # Embedded Python 3.11 runtime
├── config/
└── logs/
Each release includes a portable httpreq-{version}-linux-amd64.tar.gz archive for x86_64 Linux. Extract it to get an httpreq/ directory with a self-contained Python 3.12 runtime, then run ./httpreq from that directory (or add it to your PATH). The launcher source is PythonCaller/Linux.
httpreq/
├── httpreq # Native launcher
├── httpreq.conf → lib + python3.12/httpreq/main.pyc
├── lib/ # Embedded Python 3.12 runtime
├── config/
└── logs/
Command-line arguments passed to the launcher are forwarded to the Python entry script.
- HTTP methods — GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
- Request headers — editable key/value table with per-row enable/disable; separate views for user headers and headers actually sent
- Request body — Raw, JSON, Form Data, and File Upload
- Options — configurable timeout and SSL certificate verification
- Response view — status line and response headers
- Response body — Raw, JSON (pretty-print), and JSON Tree views; tree nodes support expand/collapse and copy (key, value, JSON fragment); Save Raw exports the full body to disk
- Binary & image bodies —
image/*responses show an inline preview fitted to its container. Click an image to focus it; useCtrl+0to fit,Ctrl+1for original size,Ctrl+2for 2× size,Ctrl+=/Ctrl+_or the mouse wheel to zoom. Oversized images provide scrollbars and drag-to-pan. Other binary bodies show a hex dump in Raw (offset, hex bytes, ASCII column) for the first 10 KB, with the remainder summarized; use Save Raw for the complete file - Large JSON — bodies over 5 MB skip JSON formatting and tree building; choosing JSON views shows a non-modal system notification and falls back to Raw
- Non-blocking UI — requests run in background threads
- HTTP logging — each request logs URL, headers, response, and errors to the console / log file
- Send history — every Send creates a new history entry (newest on top); click to open in a tab
- History management — rename, delete, and bulk delete (others / same method & URL / all)
- Linked names — renaming a tab or a history entry updates both; custom names persist in history
- Multi-tab workspace — open several requests at once; tabs are closable, draggable, and renameable (right-click tab bar)
- Tab ↔ history — opening history creates a tab if needed; deleting history closes its tab
- Session restore — window layout, splitter sizes, and open tabs persist across restarts
- Copy as curl / PowerShell — toolbar buttons or headers context menu; Linux curl line endings with WSL path conversion on Windows
- Paste headers — paste
Key: Valuelines into the request headers table - Paste curl / PowerShell command — right-click the Request Headers User table → Paste from Curl Command or Paste from PowerShell Command; fills URL, method, headers, and body. File paths in form/upload commands are resolved when the file exists (e.g. WSL
/mnt/c/...→C:\...on Windows)
curl — a single line or a command joined with \ line continuations:
curl 'https://api.example.com/users' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '{"name":"alice"}'curl -X PUT 'https://api.example.com/users/1' -H 'Accept: application/json' -d 'status=active'curl 'https://api.example.com/upload' -F 'file=@/path/to/file.bin' -k --max-time 60Supported curl flags include -X / --request, -H / --header, -d / --data / --data-raw, -F / --form, --max-time, and -k / --insecure. If -X is omitted, -d or -F implies POST (same as curl).
PowerShell — Invoke-WebRequest or Invoke-RestMethod, including multi-line commands with ` continuations. Commands copied from this app (with trailing $response output) also paste correctly; lines after the invoke call are ignored.
Invoke-WebRequest `
-Uri 'https://api.example.com/users' `
-Method POST `
-Headers @{ Authorization = 'Bearer token' } `
-ContentType 'application/json' `
-Body '{"name":"alice"}'Invoke-RestMethod -Uri 'https://api.example.com/upload' -Form @{
file = (Get-Item -LiteralPath 'C:\path\to\file.bin')
} -SkipCertificateCheck -TimeoutSec 60Mostly no. Both parsers match flags and values anywhere in the command, so -H before or after -d is fine.
Exceptions worth knowing:
| Case | curl | PowerShell |
|---|---|---|
| Flag order | Not important for supported flags | Not important for supported parameters |
| URL | The first http:// or https:// token is used |
Taken from -Uri '...' or -Uri "..." |
| Repeated body | Multiple -d / --data — last one wins |
Single -Body is read |
| Repeated form fields | Multiple -F / --form — all are kept |
All entries in -Form @{ ... } are kept |
| Method | -X overrides; otherwise -d / -F sets POST |
-Method; otherwise -Body / -Form sets POST |
Not every curl or pwsh option is supported (e.g. cookies, proxies, redirects). Paste what you copied from this app or from typical API examples; if parsing fails, a message is shown in the UI.
- Settings — click ⚙ next to + New Request for theme and editor font; Apply saves to
config.jsonwithout closing the dialog - Themes & fonts — theme colors and UI/body font sizes are in
config/config.json(themes,appearance); restart to apply manual edits - Clean UI — Fusion style with consistent tables, tabs, and context menus
- Tree view — organize requests into folders and favorites (leaf nodes with a saved request)
- Drag-drop — two modes: drag over the icon area (left of the item text) to insert as a sibling with a blue indicator line; drag over the text area to use Qt's native InternalMove (drop on a folder to add as child, drop between items to insert as sibling)
- Filter — inline filter box above the tree; type to filter items in real time; click × to clear
- Right-click — add folders/favorites, rename, delete (leaf nodes skip confirmation; non-empty folders confirm)
- Keyboard —
F2to rename,Deleteto delete the selected item - Import Postman — import a Postman collection v2.0/v2.1 JSON file as a folder tree
- Open from tree — double-click a favorite to open it in a new tab; the tab keeps the tree item's name even after sending the request
- Click + New Request to open a tab.
- Enter the URL, method, headers, and body as needed.
- Click Send to execute the request; each send adds a history entry on the left.
- Click a history item to open it in a tab (or focus the tab if already open).
- Right-click a history item for rename / delete / bulk delete (no confirmation for bulk delete); right-click a tab bar for Rename tab.
- Right-click the request headers table to copy, paste headers, or paste a curl / PowerShell command.
- Use curl / pwsh toolbar buttons to copy the current request as a command.
- Click ⚙ Settings to change theme and editor font; Apply or Save persists changes, Close closes the dialog (already-applied settings stay in effect).
Local data is stored under config/ next to the executable (or project root when running from source):
| Path | Purpose |
|---|---|
config/config.json |
App tuning, theme colors, and font/appearance settings |
config/history.json |
History list metadata (id, name, method, URL, status code/reason, time) |
config/records/{id}.json |
Full request/response payload per history entry |
config/session.json |
Window size, splitter layout, open tabs, and active side panel |
config/favorites.json |
Favorites tree (folders and request items) |
config.json keys:
| Key | Default | Meaning |
|---|---|---|
version |
1 |
Config file version |
json_format_max_bytes |
5242880 (5 MB) |
Max response body size for JSON pretty-print and JSON Tree |
binary_hex_preview_bytes |
10240 (10 KB) |
Binary hex preview length in Raw view |
binary_hex_line_width |
8 |
Hex bytes per line in binary preview |
tab_title_max_width |
400 |
Max tab title width in pixels |
themes |
— | Per-theme UI colors (solarized, light, dark); see THEME_COLOR_DOCS in ui/theme_defaults.py |
appearance |
— | Theme name, UI font sizes, and body editor font (family/size) |
Edit config/config.json and restart the app to apply changes.
These paths are listed in .gitignore and are not committed to version control.
http-requester/
├── main.py # Application entry point
├── log_util.py # Console / file logging
├── models/ # Data models (requests, history records)
├── services/ # HTTP client, curl/PowerShell import & export
├── storage/ # History, record files, session persistence
├── ui/ # PyQt5 widgets, themes, dialogs
├── pyqt_async_task.py # Background task helper
└── requirements.txt
MIT.
