Turn any website's network traffic into an OpenAPI spec and typed API clients. One command, zero dependencies.
Install · Documentation · What you get · How it works · Write a generator · Contributing
Python 3.9+ · No dependencies · Works offline · Secrets redacted automatically
See it in action
You record traffic in your browser, save it as a .har file, and run harspec. You get documentation and ready-to-use client code for an API that never had any.
Get started
- Install it (Python 3.9 or newer):
pip install harspec
- Record traffic. Open the site, press F12, go to the Network tab, use the app normally (log in, search, save something), then right click in the list and choose Save all as HAR with content.
- Run it:
harspec capture.har - Open
harspec-out/. Importopenapi.yamlinto Swagger UI, Postman or Insomnia, or copyclient.ts/client.pyinto your project.
No HAR file handy? Try the bundled sample: harspec examples/sample.har.
What you get
| File | What it is |
|---|---|
openapi.yaml |
OpenAPI 3.0.3: paths, path and query parameters (required or optional), request and response schemas per status code, examples, security schemes |
client.ts |
Typed fetch client with an interface for every request and response |
client.py |
requests-based client with a method per endpoint |
examples.sh |
One runnable curl command per endpoint |
postman_collection.json |
Postman v2.1 collection grouped by resource |
AUTH.md |
Auth summary: schemes in use, how to obtain a token, CSRF headers, cookies |
Using the generated client:
from client import Client
api = Client(token="YOUR_TOKEN")
pets = api.get_pets(params={"limit": 10})
pet = api.get_pet(42)
import { Client } from "./client";
const api = new Client({ token: "YOUR_TOKEN" });
const pets = await api.getPets({ limit: 10 }); // fully typed
How it works
| Stage | What happens |
|---|---|
| 1. Parse and filter | Reads the HAR, drops html, js, css, images, fonts and CORS preflights, keeps API calls |
| 2. Redact | Removes secrets immediately, before anything else sees the data |
| 3. Group endpoints | Turns /users/42/posts/7 into /users/{user_id}/posts/{post_id} |
| 4. Infer schemas | Merges every sample of a request or response into one schema |
| 5. Detect auth | Finds Bearer, Basic, API-key and session-cookie auth, login endpoints and CSRF headers |
| 6. Generate | Builds the OpenAPI spec, then every output format is produced from that spec |
What the inference does with your samples:
| Seen in the capture | Result in the spec |
|---|---|
| Field present in every sample | required |
| Field missing in some samples | optional |
null in some samples |
nullable: true |
| integer in one sample, decimal in another | number |
| string in one sample, number in another | oneOf |
| UUID, date-time, email, URL strings | format: uuid / date-time / email / uri |
| Numeric, UUID, hash or date path segments | path parameter |
| Same path, different status codes | one response entry per status |
Privacy and redaction
Redaction runs while the HAR is parsed, so a secret can never reach a generator, the spec or an example.
| Where | What is redacted |
|---|---|
| Headers | Authorization (scheme kept, value removed), Cookie and Set-Cookie (names kept, values removed), API-key and CSRF headers |
| JSON, form and query values | Any field named like password, token, secret, api_key, session, csrf, card, otp |
| Anywhere in a string | JWTs |
harspec makes no network requests. Everything runs on your machine. A test checks that none of the secrets from the sample HAR appear in any output file. Business data inside example values is not redacted, so skim the output before publishing it.
Command line
harspec capture.har [options]
| Option | Meaning |
|---|---|
-o, --out DIR |
Output directory (default harspec-out) |
-f, --formats LIST |
Comma list: typescript,python,curl,postman (default all) |
--host HOST |
Use one host from a multi-host capture (default: the busiest) |
--title TEXT |
Title for the OpenAPI document |
--json |
Write openapi.json instead of openapi.yaml |
--no-cluster |
Disable detection of mixed IDs such as sku123 |
--include-static |
Keep html, js, css and images |
--list-generators |
Show available generators, including plugins |
Write a generator
A generator is a function from the OpenAPI dictionary to {filename: content}:
from harspec.generators import register
@register("routes", "List of METHOD /path lines")
def routes(spec):
lines = [f"{m.upper()} {p}" for p, item in spec["paths"].items() for m in item]
return {"routes.txt": "\n".join(lines)}
Built-in generators in harspec/generators/ are about 60 lines each. Ship yours as a separate package through the harspec.generators entry-point group and harspec loads it automatically.
Wanted generators (good first pull requests): Go, Rust, Kotlin, Swift, Dart, Java, C#, PHP and Ruby clients, Bruno, Insomnia, k6 load tests, Playwright API tests, WireMock or MSW mock servers, Zod and Pydantic models, Markdown API docs.
Compatibility
| Tested | Result |
|---|---|
| Python 3.12 on Linux | 16 unit tests pass |
Generated client.ts |
Compiles with tsc --strict |
Generated client.py |
Compiles; uses requests at runtime |
openapi.yaml |
Parses with PyYAML and round-trips |
| Python 3.9, 3.11, 3.13, Windows, macOS | Run by CI on every push (3.9, 3.11, 3.13); not yet verified by hand |
HAR files from Chrome, Edge, Firefox and Safari DevTools all follow the same format. Some tools omit response bodies; then you only get paths and parameters.
Limitations
- The spec describes what you captured. Unseen endpoints, fields and error shapes are not in it. More traffic gives a better spec.
- "Required" means "present in every sample", which is a guess.
- GraphQL calls appear as one
POST /graphqloperation; per-query modelling is on the roadmap. - WebSocket traffic is ignored.
- The result is a draft. Review it before building on it.
Roadmap
- GraphQL operation extraction
-
harspec diff old.har new.harto detect API changes - Mock server from the generated spec
- Pagination and rate-limit header detection
- Merge several HAR files into one spec
- More generators (see the wanted list above)
Development
git clone https://github.com/AYUSH-PANDEY023/harspec.git
cd harspec
python -m unittest discover -s tests -v # run the tests
python examples/make_sample_har.py # rebuild the sample capture
python -m harspec examples/sample.har # run from source
There are no dependencies to install. Optional: tsc to type-check generated TypeScript, PyYAML to run the YAML round-trip test.
Contributing
Contributions are welcome, from typo fixes to new generators. Read CONTRIBUTING.md first. If harspec produces a wrong spec for a real capture, please open an issue with a redacted snippet of the traffic, what you expected, and what you got.
Legal
Use harspec only on traffic you are allowed to capture and APIs you are allowed to call. Check the terms of service of the service you are analysing. harspec is not affiliated with any other project that uses a similar name.
License
MIT. Free to use, modify and distribute.
Thank you
Thank you for trying harspec. If it saved you an afternoon, a star helps other developers find it.
Metadata
Release files for harspec 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| harspec-0.1.0.tar.gz | 26.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| harspec-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.9 kB
Release files / harspec-0.1.0.tar.gz
| Download URL | harspec-0.1.0.tar.gz |
|---|---|
| Size | 26.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e3fb1483a7eeb2f82fb9e7a8493373dc9cb04e79bb86113ddf747cab8e00f147
|
|
BLAKE2b-256 checksum How to use checksums |
177ae147e3b79a24c1afd47716f46157d52804f6be28cc7ec2e1e448d43f57b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / harspec-0.1.0-py3-none-any.whl
| Download URL | harspec-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a1bd57ca8904dd836ee6b47598f020ebc61365b3c76e8f1dd7bfb236b4264bcf
|
|
BLAKE2b-256 checksum How to use checksums |
439414deb6e318ccd7434083b75d2c80086b54163848c7c090f2cff008c6fbde
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for harspec 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.