Skip to main content

bas

Copy-paste your browser's request, bas handles the rest.

Zero dependencies. Pure Python. Just grab your headers + cookies from DevTools and go.

Why bas?

Feature bas requests pycurl curl_cffi
Zero dependencies ❌ (urllib3) ❌ (libcurl) ❌ (curl-impersonate)
Paste curl from DevTools
Auto Cookie injection ⚠️
Cookie jar (RFC 6265) ⚠️
No compilation needed
Bring your own headers ❌ (generates) ❌ (impersonation)
Works on all platforms ⚠️ ⚠️
Session persistence
Follow redirects Manual
JSON support

Installation

pip install bas-http

Quick Start

Method 1: Paste a curl command from DevTools (Recommended)

This is the fastest way. Copy a curl command from your browser and bas does the rest.

1. Open browser DevTools (F12) → Network tab
2. Make a request on the website
3. Right-click the request → "Copy as cURL"
4. Paste into Python
import bas

# Paste your curl command (use r'' raw string to preserve backslashes)
s = bas.from_curl(r'''curl "https://example.com/page" ^
  -H "accept: text/html,application/xhtml+xml" ^
  -H "accept-language: en-US,en;q=0.9" ^
  -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" ^
  -b "cf_clearance=abc123; session_id=xyz; token=def456"''')

# Now make requests — all headers and cookies are auto-injected
r = s.get("https://example.com/page")
print(r.status_code)
print(r.text)

# Follow-up requests keep the same headers and cookies
r2 = s.get("https://example.com/dashboard")
print(r2.status_code)

# Add more cookies manually if needed
s.set_cookie("new_cookie", "value", domain="example.com")
r3 = s.get("https://example.com/api/data")

Method 2: Build headers manually

If you have headers copied from DevTools (not as a curl command):

import bas

s = bas.Session()

# Paste your headers from DevTools → Network → Headers tab
s.headers = {
    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
    "accept-language": "en-US,en;q=0.9",
    "cache-control": "max-age=0",
    "sec-ch-ua": '"Chromium";v="137", "Not/A)Brand";v="24"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"Windows"',
    "sec-fetch-dest": "document",
    "sec-fetch-mode": "navigate",
    "sec-fetch-site": "none",
    "sec-fetch-user": "?1",
    "upgrade-insecure-requests": "1",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
}

# Add your cookies from DevTools → Application → Cookies
s.set_cookie("cf_clearance", "abc123", domain="example.com")
s.set_cookie("session_id", "xyz", domain="example.com")
s.set_cookie("csrf_token", "def456", domain="example.com")

# Go!
r = s.get("https://example.com/page")
print(r.status_code, len(r.text))

Method 3: Headers + cookies in one call

import bas

s = bas.from_headers(
    url="https://example.com",
    headers={
        "user-agent": "Mozilla/5.0 ...",
        "accept": "text/html,...",
    },
    cookies={
        "cf_clearance": "abc123",
        "session": "xyz",
    },
)

r = s.get("https://example.com/page")

HTTP Methods

import bas

s = bas.from_curl(r'''curl "https://example.com" -b "session=abc"''')

# GET
r = s.get("https://example.com/page")

# POST with form data
r = s.post("https://example.com/login", data={"username": "user", "password": "pass"})

# POST with JSON
r = s.post("https://example.com/api", json={"key": "value"})

# PUT
r = s.put("https://example.com/api/123", json={"name": "updated"})

# DELETE
r = s.delete("https://example.com/api/123")

# PATCH
r = s.patch("https://example.com/api/123", json={"name": "patched"})

# HEAD
r = s.head("https://example.com/page")

Response Object

r = s.get("https://example.com/page")

# Status code
print(r.status_code)        # 200
print(r.ok)                  # True (status < 400)
print(r.reason_phrase)       # "OK"

# Content
print(r.text)                # Decoded text
print(r.body)                # Raw bytes
print(r.json)                # Parsed JSON
print(r.content_type)        # "text/html; charset=utf-8"

# Headers
print(r.headers)             # Case-insensitive headers dict
print(r.headers["content-type"])

# URL info
print(r.url)                 # Final URL (after redirects)
print(r.ip)                  # Server IP
print(r.http_version)        # "1.1" or "2.0"
print(r.elapsed)             # Response time in seconds

# Redirect history
for resp in r.history:
    print(resp.status_code, resp.url)

# Raise exception on error
r.raise_for_status()  # Raises HTTPError if status >= 400

# Iterate over content
for chunk in r.iter_content(chunk_size=8192):
    process(chunk)

for line in r.iter_lines():
    print(line)

Cookie Management

Auto-injection

bas automatically injects cookies into every request. No manual header construction needed.

import bas

s = bas.from_curl(r'''curl "https://example.com" -b "session=abc123; token=xyz"''')

# This request automatically has Cookie: session=abc123; token=xyz
r = s.get("https://example.com/page")

# See what cookies were sent
print(r.request.headers.get("Cookie"))
# "session=abc123; token=xyz"

Set cookies manually

s = bas.Session()
s.set_cookie("name", "value", domain="example.com", path="/")

Get cookies for a URL

cookies = s.get_cookies("https://example.com/page")
print(cookies)  # {"session": "abc123", "token": "xyz"}

Clear all cookies

s.clear_cookies()

Save cookies to file

# JSON format
s.save_cookies("cookies.json")

# Netscape format (compatible with curl/wget)
s.save_cookies("cookies.txt", format="netscape")

Load cookies from file

s.load_cookies("cookies.json")
s.load_cookies("cookies.txt", format="netscape")

Cookie accumulation across requests

When the server sends Set-Cookie headers, bas automatically stores them:

s = bas.Session()

# Server sets cookies in this response
r1 = s.get("https://example.com/login")
# Set-Cookie: session_id=abc123; Path=/
# Set-Cookie: user=john; Path=/

# These cookies are automatically sent with the next request
r2 = s.get("https://example.com/dashboard")
# Cookie: session_id=abc123; user=john

Cookies survive redirects

# Server redirects and sets more cookies
r = s.get("https://example.com/page")
# 302 → https://example.com/dashboard
# Set-Cookie: tracking=xyz; Path=/

# ALL cookies are preserved through redirects
# No cookies lost (unlike bas!)

Session Persistence

Keep a session alive across multiple script runs:

import bas

s = bas.Session()

# Try to load previous session
try:
    s.load_cookies("my_session.json")
except FileNotFoundError:
    pass

# Make requests
r = s.get("https://example.com/page")

# Save session for next run
s.save_cookies("my_session.json")

Parse curl commands

from bas.curl_parser import parse_curl, print_curl_summary

# See what's in a curl command
print_curl_summary(r'''curl "https://example.com" -H "User-Agent: ..." -b "cookie=value"''')

# Or get it as a dict
parsed = parse_curl(r'''curl "https://example.com" -H "User-Agent: ..." -b "cookie=value"''')
print(parsed["method"])     # "GET"
print(parsed["url"])        # "https://example.com"
print(parsed["headers"])    # {"User-Agent": "..."}
print(parsed["cookies"])    # {"cookie": "value"}
print(parsed["user_agent"]) # "Mozilla/5.0 ..."
print(parsed["referer"])    # "..."

SSL Verification

# Disable SSL verification (default is enabled)
s = bas.Session(verify=False)

# Or per-request
r = s.get("https://self-signed.example.com", verify=False)

Timeouts

# Set default timeout (seconds)
s = bas.Session(timeout=60)

# Or per-request
r = s.get("https://slow.example.com", timeout=120)

Redirects

# Follow redirects (default: True)
r = s.get("https://example.com/page")

# Don't follow redirects
r = s.get("https://example.com/page", allow_redirects=False)
print(r.status_code)  # 302
print(r.location)     # "https://example.com/dashboard"

# Set max redirects
s = bas.Session(max_redirects=5)

Proxy Support

# TODO: Proxy support coming in v1.1

Real-World Example: Web Scraping

import bas

# Step 1: Copy curl from DevTools
s = bas.from_curl(r'''curl "https://spaceshooter.net/faucet/ltc" ^
  -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ^
  -H "accept-language: en-US,en;q=0.9" ^
  -H "sec-ch-ua: \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"" ^
  -H "sec-ch-ua-mobile: ?0" ^
  -H "sec-ch-ua-platform: \"Windows\"" ^
  -H "sec-fetch-dest: document" ^
  -H "sec-fetch-mode: navigate" ^
  -H "sec-fetch-site: none" ^
  -H "upgrade-insecure-requests: 1" ^
  -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" ^
  -b "captcha=rscaptcha; cf_clearance=abc123; ci_session=xyz123; uf=def456"''')

# Step 2: Make the request
r = s.get("https://spaceshooter.net/faucet/ltc")

# Step 3: Parse the response
if r.ok:
    print("Success!")
    print(f"Status: {r.status_code}")
    print(f"Content length: {len(r.text)}")
    print(f"Cookies after request: {s.get_cookies('https://spaceshooter.net')}")
else:
    print(f"Failed: {r.status_code}")

Real-World Example: Form Submission

import bas

# Copy the POST request curl from DevTools
s = bas.from_curl(r'''curl "https://example.com/login" ^
  -H "content-type: application/x-www-form-urlencoded" ^
  -H "user-agent: Mozilla/5.0 ..." ^
  -H "referer: https://example.com/login" ^
  -b "csrf_token=abc123" ^
  --data-raw "username=myuser&password=mypass"''')

r = s.post("https://example.com/login", data={
    "username": "myuser",
    "password": "mypass",
})

print(r.status_code)

Comparison with Other Libraries

requests

import requests

# Manual header/cookie setup
s = requests.Session()
s.headers["User-Agent"] = "Mozilla/5.0 ..."
s.cookies.set("session", "abc", domain="example.com")

r = s.get("https://example.com")
# Works, but no curl copy-paste support
# Generates its own fingerprint (detectable)

pycurl

import pycurl
from io import BytesIO

# Low-level, verbose setup
c = pycurl.Curl()
c.setopt(c.URL, "https://example.com")
c.setopt(c.HTTPHEADER, ["User-Agent: Mozilla/5.0 ...", "Cookie: session=abc"])
buffer = BytesIO()
c.setopt(c.WRITEDATA, buffer)
c.perform()
c.close()

# No built-in cookie jar, no redirect handling
# Requires libcurl installed on the system

curl_cffi

from curl_cffi.requests import Session

# Requires curl-impersonate installed
s = Session(impersonate="chrome131")
r = s.get("https://example.com")

# Impersonation fingerprint can become outdated
# Cookie handling has known issues

bas

import bas

# Paste curl from DevTools — done
s = bas.from_curl(r'''curl "https://example.com" -b "session=abc"''')

r = s.get("https://example.com")
# All headers auto-applied
# Cookies auto-injected
# Zero setup, zero dependencies

API Reference

bas.from_curl(curl_cmd, **kwargs) → Session

Create a Session from a curl command. Main entry point.

bas.from_headers(url, headers, cookies, **kwargs) → Session

Create a Session from raw headers and cookies.

bas.Session(headers, cookies, verify, timeout, allow_redirects, max_redirects)

Pure Python HTTP session. Zero external dependencies.

Methods:

  • get(url, **kwargs) → Response
  • post(url, **kwargs) → Response
  • put(url, **kwargs) → Response
  • delete(url, **kwargs) → Response
  • patch(url, **kwargs) → Response
  • head(url, **kwargs) → Response
  • set_cookie(name, value, domain, path) → None
  • get_cookies(url) → dict
  • clear_cookies() → None
  • save_cookies(filepath, format) → None
  • load_cookies(filepath, format) → None

bas.Cookie(name, value, domain, path, expires, max_age, secure, http_only, same_site)

Individual cookie object with RFC 6265 compliance.

bas.CookieJar

Thread-safe cookie container. Full RFC 6265 domain/path matching.

Methods:

  • add(cookie) → None
  • remove(cookie) → None
  • get(name, domain, path) → Cookie | None
  • match(url) → list[Cookie]
  • to_header(url) → str
  • parse_set_cookie(header, url) → Cookie
  • save_json(filepath) → None
  • load_json(filepath) → None
  • save_netscape(filepath) → None
  • load_netscape(filepath) → None

bas.Response

HTTP response object.

Properties:

  • status_code (int): HTTP status code
  • ok (bool): True if status < 400
  • text (str): Decoded text content
  • body (bytes): Raw bytes
  • json (Any): Parsed JSON
  • headers (Headers): Response headers
  • url (str): Final URL
  • elapsed (float): Response time
  • history (list): Redirect history
  • cookies (CookieJar): Cookie jar

License

MIT

Release files for bas-http 1.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bas-http 1.0.4
File Size Uploaded
bas_http-1.0.4.tar.gz 47.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bas-http 1.0.4
File Interpreter ABI Platform
bas_http-1.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 101.4 kB

Release files / bas_http-1.0.4.tar.gz

Download URL bas_http-1.0.4.tar.gz
Size 47.5 kB
Tags Source
SHA-256 checksum
How to use checksums
84dc4eea7827579c892bf0cdcf5add662e7d6629a45f9af0932eb78f591c4624
BLAKE2b-256 checksum
How to use checksums
11e58feba31a0b1bdc65ccfc1cf4fff7db22fff34c5371cfd6fda9b0e9feafd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / bas_http-1.0.4-py3-none-any.whl

Download URL bas_http-1.0.4-py3-none-any.whl
Size 53.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
778468bb17cfabdbdb8f05061afc4d9fcdf4933726df24bc470019af4f2daf26
BLAKE2b-256 checksum
How to use checksums
a9ceb6d8efed52e1f084ff82e55c1e8826f07959b5cca346bf4caf21cf9287c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

1.0.4 This release

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page