bas-http 1.0.1__tar.gz → 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,532 @@
1
+ Metadata-Version: 2.4
2
+ Name: bas-http
3
+ Version: 1.0.3
4
+ Summary: Copy-paste your browser's request, bas handles the rest. No impersonation needed. Zero dependencies.
5
+ Author: bas
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://pypi.org/project/bas-http/
8
+ Project-URL: Repository, https://pypi.org/project/bas-http/
9
+ Project-URL: Issues, https://pypi.org/project/bas-http/
10
+ Keywords: http,curl,cookie,scraping,browser,devtools,requests
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Internet :: WWW/HTTP
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+
26
+ # bas
27
+
28
+ Copy-paste your browser's request, bas handles the rest.
29
+
30
+ No impersonation needed. No fingerprint chasing. No broken cookies. Just grab your headers + cookies from DevTools and go.
31
+
32
+ ## Why bas?
33
+
34
+ | Problem | bas | bas |
35
+ |---------|----------|-----|
36
+ | Cookies lost during redirects | **BUG** | **Fixed** |
37
+ | Cookies not accumulating across requests | **BUG** | **Fixed** |
38
+ | Manual Cookie header construction | Yes | **Auto-injected** |
39
+ | Requires curl-impersonate | Yes | **No — pure Python** |
40
+ | Browser fingerprint updates | Constant chase | **None — bring your own headers** |
41
+ | External dependencies | Yes | **Zero** |
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install bas-http
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ### Method 1: Paste a curl command from DevTools (Recommended)
52
+
53
+ This is the fastest way. Copy a curl command from your browser and bas does the rest.
54
+
55
+ ```
56
+ 1. Open browser DevTools (F12) → Network tab
57
+ 2. Make a request on the website
58
+ 3. Right-click the request → "Copy as cURL"
59
+ 4. Paste into Python
60
+ ```
61
+
62
+ ```python
63
+ import bas
64
+
65
+ # Paste your curl command (use r'' raw string to preserve backslashes)
66
+ s = bas.from_curl(r'''curl "https://example.com/page" ^
67
+ -H "accept: text/html,application/xhtml+xml" ^
68
+ -H "accept-language: en-US,en;q=0.9" ^
69
+ -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" ^
70
+ -b "cf_clearance=abc123; session_id=xyz; token=def456"''')
71
+
72
+ # Now make requests — all headers and cookies are auto-injected
73
+ r = s.get("https://example.com/page")
74
+ print(r.status_code)
75
+ print(r.text)
76
+
77
+ # Follow-up requests keep the same headers and cookies
78
+ r2 = s.get("https://example.com/dashboard")
79
+ print(r2.status_code)
80
+
81
+ # Add more cookies manually if needed
82
+ s.set_cookie("new_cookie", "value", domain="example.com")
83
+ r3 = s.get("https://example.com/api/data")
84
+ ```
85
+
86
+ ### Method 2: Build headers manually
87
+
88
+ If you have headers copied from DevTools (not as a curl command):
89
+
90
+ ```python
91
+ import bas
92
+
93
+ s = bas.Session()
94
+
95
+ # Paste your headers from DevTools → Network → Headers tab
96
+ s.headers = {
97
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
98
+ "accept-language": "en-US,en;q=0.9",
99
+ "cache-control": "max-age=0",
100
+ "sec-ch-ua": '"Chromium";v="137", "Not/A)Brand";v="24"',
101
+ "sec-ch-ua-mobile": "?0",
102
+ "sec-ch-ua-platform": '"Windows"',
103
+ "sec-fetch-dest": "document",
104
+ "sec-fetch-mode": "navigate",
105
+ "sec-fetch-site": "none",
106
+ "sec-fetch-user": "?1",
107
+ "upgrade-insecure-requests": "1",
108
+ "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",
109
+ }
110
+
111
+ # Add your cookies from DevTools → Application → Cookies
112
+ s.set_cookie("cf_clearance", "abc123", domain="example.com")
113
+ s.set_cookie("session_id", "xyz", domain="example.com")
114
+ s.set_cookie("csrf_token", "def456", domain="example.com")
115
+
116
+ # Go!
117
+ r = s.get("https://example.com/page")
118
+ print(r.status_code, len(r.text))
119
+ ```
120
+
121
+ ### Method 3: Headers + cookies in one call
122
+
123
+ ```python
124
+ import bas
125
+
126
+ s = bas.from_headers(
127
+ url="https://example.com",
128
+ headers={
129
+ "user-agent": "Mozilla/5.0 ...",
130
+ "accept": "text/html,...",
131
+ },
132
+ cookies={
133
+ "cf_clearance": "abc123",
134
+ "session": "xyz",
135
+ },
136
+ )
137
+
138
+ r = s.get("https://example.com/page")
139
+ ```
140
+
141
+ ## HTTP Methods
142
+
143
+ ```python
144
+ import bas
145
+
146
+ s = bas.from_curl(r'''curl "https://example.com" -b "session=abc"''')
147
+
148
+ # GET
149
+ r = s.get("https://example.com/page")
150
+
151
+ # POST with form data
152
+ r = s.post("https://example.com/login", data={"username": "user", "password": "pass"})
153
+
154
+ # POST with JSON
155
+ r = s.post("https://example.com/api", json={"key": "value"})
156
+
157
+ # PUT
158
+ r = s.put("https://example.com/api/123", json={"name": "updated"})
159
+
160
+ # DELETE
161
+ r = s.delete("https://example.com/api/123")
162
+
163
+ # PATCH
164
+ r = s.patch("https://example.com/api/123", json={"name": "patched"})
165
+
166
+ # HEAD
167
+ r = s.head("https://example.com/page")
168
+ ```
169
+
170
+ ## Response Object
171
+
172
+ ```python
173
+ r = s.get("https://example.com/page")
174
+
175
+ # Status code
176
+ print(r.status_code) # 200
177
+ print(r.ok) # True (status < 400)
178
+ print(r.reason_phrase) # "OK"
179
+
180
+ # Content
181
+ print(r.text) # Decoded text
182
+ print(r.body) # Raw bytes
183
+ print(r.json) # Parsed JSON
184
+ print(r.content_type) # "text/html; charset=utf-8"
185
+
186
+ # Headers
187
+ print(r.headers) # Case-insensitive headers dict
188
+ print(r.headers["content-type"])
189
+
190
+ # URL info
191
+ print(r.url) # Final URL (after redirects)
192
+ print(r.ip) # Server IP
193
+ print(r.http_version) # "1.1" or "2.0"
194
+ print(r.elapsed) # Response time in seconds
195
+
196
+ # Redirect history
197
+ for resp in r.history:
198
+ print(resp.status_code, resp.url)
199
+
200
+ # Raise exception on error
201
+ r.raise_for_status() # Raises HTTPError if status >= 400
202
+
203
+ # Iterate over content
204
+ for chunk in r.iter_content(chunk_size=8192):
205
+ process(chunk)
206
+
207
+ for line in r.iter_lines():
208
+ print(line)
209
+ ```
210
+
211
+ ## Cookie Management
212
+
213
+ ### Auto-injection
214
+
215
+ bas automatically injects cookies into every request. No manual header construction needed.
216
+
217
+ ```python
218
+ import bas
219
+
220
+ s = bas.from_curl(r'''curl "https://example.com" -b "session=abc123; token=xyz"''')
221
+
222
+ # This request automatically has Cookie: session=abc123; token=xyz
223
+ r = s.get("https://example.com/page")
224
+
225
+ # See what cookies were sent
226
+ print(r.request.headers.get("Cookie"))
227
+ # "session=abc123; token=xyz"
228
+ ```
229
+
230
+ ### Set cookies manually
231
+
232
+ ```python
233
+ s = bas.Session()
234
+ s.set_cookie("name", "value", domain="example.com", path="/")
235
+ ```
236
+
237
+ ### Get cookies for a URL
238
+
239
+ ```python
240
+ cookies = s.get_cookies("https://example.com/page")
241
+ print(cookies) # {"session": "abc123", "token": "xyz"}
242
+ ```
243
+
244
+ ### Clear all cookies
245
+
246
+ ```python
247
+ s.clear_cookies()
248
+ ```
249
+
250
+ ### Save cookies to file
251
+
252
+ ```python
253
+ # JSON format
254
+ s.save_cookies("cookies.json")
255
+
256
+ # Netscape format (compatible with curl/wget)
257
+ s.save_cookies("cookies.txt", format="netscape")
258
+ ```
259
+
260
+ ### Load cookies from file
261
+
262
+ ```python
263
+ s.load_cookies("cookies.json")
264
+ s.load_cookies("cookies.txt", format="netscape")
265
+ ```
266
+
267
+ ### Cookie accumulation across requests
268
+
269
+ When the server sends Set-Cookie headers, bas automatically stores them:
270
+
271
+ ```python
272
+ s = bas.Session()
273
+
274
+ # Server sets cookies in this response
275
+ r1 = s.get("https://example.com/login")
276
+ # Set-Cookie: session_id=abc123; Path=/
277
+ # Set-Cookie: user=john; Path=/
278
+
279
+ # These cookies are automatically sent with the next request
280
+ r2 = s.get("https://example.com/dashboard")
281
+ # Cookie: session_id=abc123; user=john
282
+ ```
283
+
284
+ ### Cookies survive redirects
285
+
286
+ ```python
287
+ # Server redirects and sets more cookies
288
+ r = s.get("https://example.com/page")
289
+ # 302 → https://example.com/dashboard
290
+ # Set-Cookie: tracking=xyz; Path=/
291
+
292
+ # ALL cookies are preserved through redirects
293
+ # No cookies lost (unlike bas!)
294
+ ```
295
+
296
+ ## Session Persistence
297
+
298
+ Keep a session alive across multiple script runs:
299
+
300
+ ```python
301
+ import bas
302
+
303
+ s = bas.Session()
304
+
305
+ # Try to load previous session
306
+ try:
307
+ s.load_cookies("my_session.json")
308
+ except FileNotFoundError:
309
+ pass
310
+
311
+ # Make requests
312
+ r = s.get("https://example.com/page")
313
+
314
+ # Save session for next run
315
+ s.save_cookies("my_session.json")
316
+ ```
317
+
318
+ ## Parse curl commands
319
+
320
+ ```python
321
+ from bas.curl_parser import parse_curl, print_curl_summary
322
+
323
+ # See what's in a curl command
324
+ print_curl_summary(r'''curl "https://example.com" -H "User-Agent: ..." -b "cookie=value"''')
325
+
326
+ # Or get it as a dict
327
+ parsed = parse_curl(r'''curl "https://example.com" -H "User-Agent: ..." -b "cookie=value"''')
328
+ print(parsed["method"]) # "GET"
329
+ print(parsed["url"]) # "https://example.com"
330
+ print(parsed["headers"]) # {"User-Agent": "..."}
331
+ print(parsed["cookies"]) # {"cookie": "value"}
332
+ print(parsed["user_agent"]) # "Mozilla/5.0 ..."
333
+ print(parsed["referer"]) # "..."
334
+ ```
335
+
336
+ ## SSL Verification
337
+
338
+ ```python
339
+ # Disable SSL verification (default is enabled)
340
+ s = bas.Session(verify=False)
341
+
342
+ # Or per-request
343
+ r = s.get("https://self-signed.example.com", verify=False)
344
+ ```
345
+
346
+ ## Timeouts
347
+
348
+ ```python
349
+ # Set default timeout (seconds)
350
+ s = bas.Session(timeout=60)
351
+
352
+ # Or per-request
353
+ r = s.get("https://slow.example.com", timeout=120)
354
+ ```
355
+
356
+ ## Redirects
357
+
358
+ ```python
359
+ # Follow redirects (default: True)
360
+ r = s.get("https://example.com/page")
361
+
362
+ # Don't follow redirects
363
+ r = s.get("https://example.com/page", allow_redirects=False)
364
+ print(r.status_code) # 302
365
+ print(r.location) # "https://example.com/dashboard"
366
+
367
+ # Set max redirects
368
+ s = bas.Session(max_redirects=5)
369
+ ```
370
+
371
+ ## Proxy Support
372
+
373
+ ```python
374
+ # TODO: Proxy support coming in v1.1
375
+ ```
376
+
377
+ ## Real-World Example: Web Scraping
378
+
379
+ ```python
380
+ import bas
381
+
382
+ # Step 1: Copy curl from DevTools
383
+ s = bas.from_curl(r'''curl "https://spaceshooter.net/faucet/ltc" ^
384
+ -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ^
385
+ -H "accept-language: en-US,en;q=0.9" ^
386
+ -H "sec-ch-ua: \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"" ^
387
+ -H "sec-ch-ua-mobile: ?0" ^
388
+ -H "sec-ch-ua-platform: \"Windows\"" ^
389
+ -H "sec-fetch-dest: document" ^
390
+ -H "sec-fetch-mode: navigate" ^
391
+ -H "sec-fetch-site: none" ^
392
+ -H "upgrade-insecure-requests: 1" ^
393
+ -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" ^
394
+ -b "captcha=rscaptcha; cf_clearance=abc123; ci_session=xyz123; uf=def456"''')
395
+
396
+ # Step 2: Make the request
397
+ r = s.get("https://spaceshooter.net/faucet/ltc")
398
+
399
+ # Step 3: Parse the response
400
+ if r.ok:
401
+ print("Success!")
402
+ print(f"Status: {r.status_code}")
403
+ print(f"Content length: {len(r.text)}")
404
+ print(f"Cookies after request: {s.get_cookies('https://spaceshooter.net')}")
405
+ else:
406
+ print(f"Failed: {r.status_code}")
407
+ ```
408
+
409
+ ## Real-World Example: Form Submission
410
+
411
+ ```python
412
+ import bas
413
+
414
+ # Copy the POST request curl from DevTools
415
+ s = bas.from_curl(r'''curl "https://example.com/login" ^
416
+ -H "content-type: application/x-www-form-urlencoded" ^
417
+ -H "user-agent: Mozilla/5.0 ..." ^
418
+ -H "referer: https://example.com/login" ^
419
+ -b "csrf_token=abc123" ^
420
+ --data-raw "username=myuser&password=mypass"''')
421
+
422
+ r = s.post("https://example.com/login", data={
423
+ "username": "myuser",
424
+ "password": "mypass",
425
+ })
426
+
427
+ print(r.status_code)
428
+ ```
429
+
430
+ ## Comparison with bas
431
+
432
+ ### bas (BROKEN)
433
+
434
+ ```python
435
+ from curl_cffi.requests import Session
436
+
437
+ s = Session(impersonate="chrome131")
438
+
439
+ # Cookies lost during redirects!
440
+ r1 = s.get("https://example.com/page") # 302 redirect
441
+ # r1 is missing cookies from Set-Cookie headers!
442
+
443
+ # Cookies not accumulating!
444
+ r2 = s.get("https://example.com/page")
445
+ # r2 has LOST cookies from r1!
446
+ ```
447
+
448
+ ### bas (FIXED)
449
+
450
+ ```python
451
+ import bas
452
+
453
+ s = bas.from_curl(r'''curl "https://example.com" -b "session=abc"''')
454
+
455
+ # Cookies survive redirects!
456
+ r1 = s.get("https://example.com/page") # 302 redirect
457
+ # ALL cookies preserved through redirect
458
+
459
+ # Cookies accumulate!
460
+ r2 = s.get("https://example.com/dashboard")
461
+ # r2 has ALL cookies from r1 + new ones
462
+
463
+ # No manual Cookie header needed!
464
+ # bas auto-injects cookies from the jar
465
+ ```
466
+
467
+ ## API Reference
468
+
469
+ ### `bas.from_curl(curl_cmd, **kwargs)` → Session
470
+
471
+ Create a Session from a curl command. Main entry point.
472
+
473
+ ### `bas.from_headers(url, headers, cookies, **kwargs)` → Session
474
+
475
+ Create a Session from raw headers and cookies.
476
+
477
+ ### `bas.Session(headers, cookies, verify, timeout, allow_redirects, max_redirects)`
478
+
479
+ Pure Python HTTP session. Zero external dependencies.
480
+
481
+ **Methods:**
482
+ - `get(url, **kwargs)` → Response
483
+ - `post(url, **kwargs)` → Response
484
+ - `put(url, **kwargs)` → Response
485
+ - `delete(url, **kwargs)` → Response
486
+ - `patch(url, **kwargs)` → Response
487
+ - `head(url, **kwargs)` → Response
488
+ - `set_cookie(name, value, domain, path)` → None
489
+ - `get_cookies(url)` → dict
490
+ - `clear_cookies()` → None
491
+ - `save_cookies(filepath, format)` → None
492
+ - `load_cookies(filepath, format)` → None
493
+
494
+ ### `bas.Cookie(name, value, domain, path, expires, max_age, secure, http_only, same_site)`
495
+
496
+ Individual cookie object with RFC 6265 compliance.
497
+
498
+ ### `bas.CookieJar`
499
+
500
+ Thread-safe cookie container. Full RFC 6265 domain/path matching.
501
+
502
+ **Methods:**
503
+ - `add(cookie)` → None
504
+ - `remove(cookie)` → None
505
+ - `get(name, domain, path)` → Cookie | None
506
+ - `match(url)` → list[Cookie]
507
+ - `to_header(url)` → str
508
+ - `parse_set_cookie(header, url)` → Cookie
509
+ - `save_json(filepath)` → None
510
+ - `load_json(filepath)` → None
511
+ - `save_netscape(filepath)` → None
512
+ - `load_netscape(filepath)` → None
513
+
514
+ ### `bas.Response`
515
+
516
+ HTTP response object.
517
+
518
+ **Properties:**
519
+ - `status_code` (int): HTTP status code
520
+ - `ok` (bool): True if status < 400
521
+ - `text` (str): Decoded text content
522
+ - `body` (bytes): Raw bytes
523
+ - `json` (Any): Parsed JSON
524
+ - `headers` (Headers): Response headers
525
+ - `url` (str): Final URL
526
+ - `elapsed` (float): Response time
527
+ - `history` (list): Redirect history
528
+ - `cookies` (CookieJar): Cookie jar
529
+
530
+ ## License
531
+
532
+ MIT
@@ -6,7 +6,7 @@ No impersonation needed. No fingerprint chasing. No broken cookies. Just grab yo
6
6
 
7
7
  ## Why bas?
8
8
 
9
- | Problem | curlcffi | bas |
9
+ | Problem | bas | bas |
10
10
  |---------|----------|-----|
11
11
  | Cookies lost during redirects | **BUG** | **Fixed** |
12
12
  | Cookies not accumulating across requests | **BUG** | **Fixed** |
@@ -265,7 +265,7 @@ r = s.get("https://example.com/page")
265
265
  # Set-Cookie: tracking=xyz; Path=/
266
266
 
267
267
  # ALL cookies are preserved through redirects
268
- # No cookies lost (unlike curlcffi!)
268
+ # No cookies lost (unlike bas!)
269
269
  ```
270
270
 
271
271
  ## Session Persistence
@@ -402,9 +402,9 @@ r = s.post("https://example.com/login", data={
402
402
  print(r.status_code)
403
403
  ```
404
404
 
405
- ## Comparison with curlcffi
405
+ ## Comparison with bas
406
406
 
407
- ### curlcffi (BROKEN)
407
+ ### bas (BROKEN)
408
408
 
409
409
  ```python
410
410
  from curl_cffi.requests import Session
@@ -28,7 +28,7 @@ from .curl_parser import parse_curl, curl_to_session, print_curl_summary
28
28
  from .cookies import Cookie, CookieJar
29
29
  from .models import Headers, PreparedRequest, Response, HTTPError
30
30
 
31
- __version__ = "1.0.1"
31
+ __version__ = "1.0.3"
32
32
  __author__ = "bas"
33
33
 
34
34
 
@@ -2,7 +2,7 @@
2
2
  Low-level ctypes bindings for libcurl with curl-impersonate support.
3
3
 
4
4
  This module provides Python bindings to libcurl (or curl-impersonate if available)
5
- using ctypes. It avoids cffi compilation issues that plague curlcffi.
5
+ using ctypes. It avoids cffi compilation issues that plague bas.
6
6
  """
7
7
 
8
8
  import ctypes
@@ -1,7 +1,7 @@
1
1
  """
2
2
  RFC 6265 compliant CookieJar.
3
3
 
4
- This module fixes the major cookie issues in curlcffi:
4
+ This module fixes the major cookie issues in bas:
5
5
  1. Cookies lost during redirects (#55)
6
6
  2. Cookies not accumulating across session requests (#582)
7
7
  3. Need for manual cookie header management
@@ -226,7 +226,7 @@ class CookieJar:
226
226
  """
227
227
  Thread-safe, RFC 6265 compliant cookie jar.
228
228
 
229
- This is the heart of bas's cookie handling. Unlike curlcffi's
229
+ This is the heart of bas's cookie handling. Unlike bas's
230
230
  approach (which relies on libcurl's internal cookie engine and loses
231
231
  cookies during redirects), bas manages cookies entirely in Python.
232
232
 
@@ -5,7 +5,7 @@ This module provides browser fingerprint profiles that override HTTP/2
5
5
  settings and headers to mimic real browsers. When curl-impersonate is
6
6
  available, it also enables TLS fingerprint mimicry.
7
7
 
8
- Unlike curlcffi which bundles impersonation in a single enum, bas
8
+ Unlike bas which bundles impersonation in a single enum, bas
9
9
  separates the concerns:
10
10
  - TLS impersonation (requires curl-impersonate library)
11
11
  - HTTP/2 fingerprinting (works with standard libcurl)
@@ -348,7 +348,7 @@ PROFILES: dict[str, BrowserProfile] = {
348
348
  "edge131": EDGE131,
349
349
  }
350
350
 
351
- # Aliases for curlcffi compatibility
351
+ # Aliases for bas compatibility
352
352
  CHROME_ALIASES = {
353
353
  "chrome": CHROME131,
354
354
  "chrome99": CHROME131, # closest available
@@ -385,7 +385,7 @@ def get_profile(name: str) -> BrowserProfile:
385
385
  """
386
386
  Get a browser profile by name.
387
387
 
388
- Supports both exact names and curlcffi-compatible aliases.
388
+ Supports both exact names and bas-compatible aliases.
389
389
 
390
390
  Args:
391
391
  name: Profile name (e.g., "chrome131", "firefox120", "chrome")
@@ -2,7 +2,7 @@
2
2
  Session-based HTTP client with proper cookie management.
3
3
 
4
4
  This is the main public API of bas. It provides a requests-like
5
- interface while fixing ALL of curlcffi's cookie bugs:
5
+ interface while fixing ALL of bas's cookie bugs:
6
6
 
7
7
  Fix #1: Cookies accumulate correctly across requests in a session
8
8
  Fix #2: Cookies are inherited during redirects (even cross-domain)
@@ -92,7 +92,7 @@ class Session:
92
92
  """
93
93
  A persistent HTTP session with automatic cookie management.
94
94
 
95
- Key improvements over curlcffi.Session:
95
+ Key improvements over bas.Session:
96
96
  - Cookies ALWAYS accumulate across requests (fixes #582)
97
97
  - Cookies are inherited during redirects (fixes #55)
98
98
  - Automatic Cookie header injection (no manual construction)
@@ -358,7 +358,7 @@ class Session:
358
358
  )
359
359
 
360
360
  # ── CRITICAL: Parse Set-Cookie and update our jar ──
361
- # This is what curlcffi gets wrong — it relies on curl's internal
361
+ # This is what bas gets wrong — it relies on curl's internal
362
362
  # cookie engine which loses cookies during redirects.
363
363
  self._cookie_jar.parse_set_cookie_headers(
364
364
  response_headers,
@@ -485,7 +485,7 @@ class Session:
485
485
  3. Re-apply cookies for the next request via our jar
486
486
  4. Never lose a single cookie
487
487
 
488
- This fixes curlcffi issue #55 where cookies were lost during redirects.
488
+ This fixes bas issue #55 where cookies were lost during redirects.
489
489
  """
490
490
  if history is None:
491
491
  history = []
@@ -508,7 +508,7 @@ class Session:
508
508
  redirect_url = urljoin(response.url, location)
509
509
 
510
510
  # ── COOKIE FIX: Parse Set-Cookie before redirect ──
511
- # curlcffi loses cookies here because it switches to curl's
511
+ # bas loses cookies here because it switches to curl's
512
512
  # internal cookie engine for the redirect. We don't.
513
513
  # (Already done in _curl_perform above)
514
514