Metadata-Version: 2.4
Name: network-limiter
Version: 1.0.1
Summary: Per-process network bandwidth limiter for Windows (library + GUI), built on WinDivert.
Project-URL: Homepage, https://github.com/EmperorHeyman/network-limiter
Project-URL: Repository, https://github.com/EmperorHeyman/network-limiter
Project-URL: Issues, https://github.com/EmperorHeyman/network-limiter/issues
Author-email: Lukáš Peterek <lpeterek@rapl-group.eu>
License: MIT
License-File: LICENSE
Keywords: bandwidth,limiter,network,throttle,traffic-shaping,windivert,windows
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Win32 (MS Windows)
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Networking :: Monitoring
Requires-Python: >=3.10
Requires-Dist: psutil>=5.9
Requires-Dist: pydivert>=2.1
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pyinstaller>=6.0; extra == 'dev'
Requires-Dist: pyqt6>=6.5; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Provides-Extra: gui
Requires-Dist: pyqt6>=6.5; extra == 'gui'
Description-Content-Type: text/markdown

# Network Limiter

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
[![Platform](https://img.shields.io/badge/platform-Windows-lightgrey.svg)](#requirements)

**Per-process network bandwidth limiter for Windows.** Throttle the download
and upload speed of *individual applications* (by PID) in real time, built on
[WinDivert](https://reqrypt.org/windivert.html) (`pydivert`) and `psutil`.

Ships as two things:

- **A library** (`network_limiter`) — a clean, GUI-free API you can drive from
  your own Python code.
- **A desktop GUI** (optional `[gui]` extra) — a live per-process traffic table
  with toolbar, status bar, and inline limit editing.

> ⚠️ **Windows only.** WinDivert is a Windows kernel driver and requires
> **Administrator privileges**.

---

## Features

- Throttle download and/or upload speed per process (KB/s).
- Live per-application throughput monitoring.
- Works with TCP and UDP, including QUIC / HTTP3 (wildcard-bound UDP fallback).
- Use it as a **library** (no GUI dependency) or as a **desktop app**.
- Modern dark-themed GUI: toolbar, search, status bar with admin indicator, and
  double-click inline limit editing.

---

## Requirements

- Windows 10 / 11
- Python 3.10+
- Administrator privileges (WinDivert)

---

## Installation

### As a library (no GUI)

```powershell
pip install network-limiter
```

### With the desktop GUI

```powershell
pip install "network-limiter[gui]"
```

### From source

```powershell
git clone https://github.com/EmperorHeyman/network-limiter.git
cd network-limiter
pip install ".[gui]"        # or: pip install .   (library only)
```

---

## Library usage

The core engine is `NetworkLimiter`. It runs its capture/throttle loop on a
background thread, so you start it, set limits, and stop it whenever you like.

```python
from network_limiter import NetworkLimiter, find_pids_by_name, list_processes

# 1. List running processes
for proc in list_processes()[:5]:
    print(proc["pid"], proc["name"])

# 2. Start the engine (needs Administrator)
limiter = NetworkLimiter()
limiter.start()

# 3. Limit every Chrome process to 500 KB/s down, 100 KB/s up
for pid in find_pids_by_name("chrome.exe"):
    limiter.set_limit(pid, down_kbs=500, up_kbs=100)

# 4. Inspect current limits
print(limiter.get_limits())

# 5. Remove limits and stop
limiter.clear_limit()      # clear all (or pass a pid to clear one)
limiter.stop()
```

### Context manager

```python
from network_limiter import NetworkLimiter

with NetworkLimiter() as limiter:
    limiter.set_limit(1234, down_kbs=1000)   # 0 = unlimited for that direction
    input("Throttling PID 1234... press Enter to stop")
# engine stops automatically on exit
```

### Live stats via callbacks

Callbacks fire on the engine's background thread (marshal to your UI thread if
needed):

```python
from network_limiter import NetworkLimiter

def on_stats(rows):
    for row in rows[:3]:
        print(f"{row['name']:<25} ↓{row['down_kbs']:.1f} ↑{row['up_kbs']:.1f} KB/s")

limiter = NetworkLimiter(
    on_stats=on_stats,
    on_status=print,
    on_error=lambda msg: print("ERROR:", msg),
)
limiter.start()
```

### API summary

| Member | Description |
| --- | --- |
| `NetworkLimiter(packet_filter, on_stats, on_status, on_error, on_limits_changed)` | Create an engine. |
| `.start()` / `.stop(timeout=5.0)` | Start / stop the background loop. |
| `.set_limit(pid, down_kbs=0, up_kbs=0, name=None)` | Throttle a PID (`0` = unlimited). |
| `.clear_limit(pid=None)` | Remove one limit, or all when `pid` is `None`. |
| `.get_limits()` / `.get_stats()` | Current limits / latest throughput. |
| `.running` | Whether the loop is alive. |
| `list_processes()` | `[{"pid", "name"}, ...]` snapshot. |
| `find_pids_by_name(name)` | PIDs whose name matches (substring, case-insensitive). |

---

## GUI usage

After installing with the `[gui]` extra:

```powershell
network-limiter
```

or

```powershell
python -m network_limiter
```

The app relaunches itself elevated via UAC. **Double-click a `Limit ↓` or
`Limit ↑` cell** to throttle that app inline, use the toolbar to clear limits,
and the search box to filter. The status bar shows the monitor state and
whether you are running as Administrator.

---

## Build a standalone .exe

A [PyInstaller](https://pyinstaller.org/) spec is included. It bundles the
WinDivert driver and requests elevation (`uac_admin`).

```powershell
pip install ".[dev]"
pyinstaller network_limiter.spec
# -> dist/network_limiter.exe
```

---

## How it works

WinDivert intercepts packets in the kernel and hands them to user space.
`network_limiter` maps each packet to a PID via `psutil` connection tables
(with a port-only fallback for wildcard-bound UDP sockets used by QUIC/HTTP3),
then delays packets for throttled PIDs using a sliding-window rate calculation
before re-injecting them. Unthrottled traffic passes straight through.

---

## License

[MIT](LICENSE) © 2026 Lukáš Peterek
