Convert .http files to Postman collections in one command.
JetBrains HTTP Client and VS Code REST Client requests (.http / .rest
files) import cleanly into Postman as a Collection v2.1 JSON file —
requests, folders, variables, scripts, auth, and bodies included.
auth.http ├── no runtime dependencies
users.http │
orders.http ▼
http2postman apis/ -o collection.json → Import into Postman ✓
You built your whole API workflow in .http files — in IntelliJ, PyCharm,
Android Studio, or VS Code. Now a teammate uses Postman, or you need to share
requests with someone who does. Re-typing every request, header, and body by
hand is tedious and error-prone.
http2postman does the migration for you, in seconds:
pip install http2postman
http2postman requests.http
# ✓ 12 requests | 3 folders | 5 variables | 2 scripts → postman_collection.jsonThen Postman → Import → postman_collection.json (Postman docs). Done.
Before — requests.http (JetBrains / REST Client format):
@baseUrl = https://api.example.com
### List users
GET {{baseUrl}}/users
Authorization: Bearer {{token}}
### Create user
POST {{baseUrl}}/users
Content-Type: application/json
{ "name": "Ada", "role": "engineer" }
# @name login
POST {{baseUrl}}/auth/token
Content-Type: application/x-www-form-urlencoded
X-REQUEST-TYPE: GraphQL
{ "query": "{ viewer { login } }" }After — http2postman requests.http produces a Postman v2.1 collection:
- ✅ Named requests (
### List users,# @name login) - ✅
@baseUrl→ collection variable,{{var}}tokens preserved - ✅ JSON / form / GraphQL / multipart / raw bodies
- ✅
## Folder/@group→ Postman folders - ✅
Bearer/Basic/ OAuth2 headers → real Postman auth objects - ✅ JetBrains
< {% %}/> {% %}scripts → Pre-request / Tests tabs
- Zero dependencies — pure Python standard library, single CLI
- Directories —
http2postman apis/recursively merges every.http/.restfile - Environments —
--prefer-env devbakes JetBrainshttp-client.env.jsonvalues in as collection variable defaults - Dotenv —
{{$dotenv VAR}}resolves from the.envnext to each file - Dynamic variables —
$uuid→{{$guid}},$random.email→{{$randomEmail}}, and more - Honest reporting — anything Postman can't express (WebSocket, gRPC) is
listed with a
file:linereference for manual porting; nothing is silently dropped - Safe — source files are never modified; output is written atomically
pip install http2postmanOr run directly from a checkout, no install needed:
python3 -m http2postman requests.httpOn externally managed Python (Debian/Ubuntu, PEP 668), use a virtual environment:
python3 -m venv .venv
source .venv/bin/activate # note: `source`, not execute
pip install http2postmanhttp2postman requests.http
http2postman requests.http -o my-collection.json
http2postman apis/ --name "My API" # recursively scans directories
http2postman a.http b.http --quiet
http2postman requests.http --prefer-env dev # bake env values into collection variables
http2postman requests.http --env-file .env # resolve {{$dotenv VAR}} from a specific file
python3 -m http2postman requests.http-o OUTPUT— output JSON path (defaultpostman_collection.jsonnext to the input).--name NAME— collection name (default: first input file's basename).--env-file PATH—.envfile for{{$dotenv VAR}}resolution (default:.envnext to each input).--prefer-env NAME— use the named environment fromhttp-client.env.json(plushttp-client.private.env.json, merged on top) next to the first input as default values for the collection variables. Environment values win over file-level@vardefinitions; scalar values are coerced to strings, complex values to compact JSON. Missing file or environment name is an error (exit 1).--quiet— suppress the stdout report.
Exit codes: 0 success, 1 conversion/validation failure, 2 usage error.
Output is written atomically (temp file + rename); source files are never modified.
JetBrains environment files map environment names to variable values:
// http-client.env.json (next to the .http file)
{
"dev": { "baseUrl": "https://dev.example.com", "apiKey": "dev-key" },
"prod": { "baseUrl": "https://prod.example.com" }
}http2postman requests.http --prefer-env dev
# -> collection variables: baseUrl = https://dev.example.com, apiKey = dev-keySecrets can live in http-client.private.env.json (same shape, merged on
top). The report prints Env: dev so you can see which environment was used.
###request names,# @nameoverrides, all HTTP methods (unknown methods pass through verbatim)- headers (order/casing preserved;
Content-Lengthdropped) - raw / JSON / XML / urlencoded / multipart / external-file bodies
- GraphQL requests via
X-REQUEST-TYPE: GraphQL - file-level
@name = valuevariables -> collection variables {{var}}tokens (kept byte-for-byte), JetBrains dynamic variables mapped to Postman equivalents ($uuid->{{$guid}},$random.email->{{$randomEmail}}, etc. — unlisted$random.*tokens are reported)## Folder/@groupfolder grouping- JetBrains environments:
--prefer-env NAMEuses the values fromhttp-client.env.json/http-client.private.env.jsonas the collection variable defaults (see the example above). - Scripts:
< {% ... %}pre-request and> {% ... %}response scripts are captured and translated into Postman Pre-request Script / Tests tabs (client.test->pm.test,client.assert->pm.expect(!!(cond)[, msg]).to.be.true— JetBrains' assert is a truthiness check, and Postman's sandbox does not support Chai's.truthy, so the condition is boolean-coerced with!!()and asserted with the documented.to.be.true—,client.global.set->pm.collectionVariables.set,request.variables.set->pm.variables.set,request.environment.get->pm.variables.get(resolves through the Postman variable chain, so--prefer-envdefaults are visible to scripts),response.status->pm.response.code,response.body->pm.response.json()(parsed body, like JetBrains),response.contentType/time->pm.response.*, ...). Unrecognized statements pass through unchanged. - dotenv:
{{$dotenv VAR}}references resolve from the.envfile next to each input file, or the file given with--env-file. Unresolved references are kept as-is and reported. - Auth: OAuth2 client-credentials token requests (POST to a token/oauth
URL with
grant_type=client_credentialsand a literalBasicheader) get a Postmanoauth2auth object;Bearer {{token}}and literalBasic base64(user:pass)/Basic {{user}} {{pass}}headers becomebearer/basicauth objects (the header is removed). - WebSocket (
WEBSOCKET ws://...) and gRPC (GRPC host/service/method) blocks are parsed and reported underUnsupported:— the Postman Collection v2.1 schema cannot express them — with afile:linereference for manual porting.
The stdout report lists Requests: N | Folders: N | Variables: N | Scripts: N (translated script blocks), an Env: line when --prefer-env is
used, and an Unsupported: line for anything left (unmapped dynamic
variables, unresolved dotenv refs, WebSocket/gRPC blocks).
- IntelliJ / PyCharm / WebStorm / Android Studio — HTTP Client
files under
src/test/http,http/, or anywhere in the project. First-party export is still open as IJPL-150186 — vote there;http2postmanbridges the gap meanwhile. - VS Code REST Client — same syntax,
including
.restfiles - Bruno? open an issue — multi-format support is planned
python3 -m unittest discover -s testsIssues and PRs are welcome — especially conversion edge cases from real-world
.http files. If output doesn't import into Postman, open an
issue with a (redacted)
sample file.
MIT — see LICENSE.
