Scweet 5.2__tar.gz → 5.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.
Files changed (70) hide show
  1. {scweet-5.2 → scweet-5.3}/CHANGELOG.md +15 -0
  2. {scweet-5.2 → scweet-5.3}/DOCUMENTATION.md +19 -9
  3. scweet-5.3/PKG-INFO +314 -0
  4. scweet-5.3/README.md +273 -0
  5. {scweet-5.2 → scweet-5.3}/Scweet/__version__.py +1 -1
  6. {scweet-5.2 → scweet-5.3}/Scweet/cli.py +3 -0
  7. {scweet-5.2 → scweet-5.3}/Scweet/client.py +8 -0
  8. scweet-5.3/Scweet.egg-info/PKG-INFO +314 -0
  9. scweet-5.2/PKG-INFO +0 -210
  10. scweet-5.2/README.md +0 -169
  11. scweet-5.2/Scweet.egg-info/PKG-INFO +0 -210
  12. {scweet-5.2 → scweet-5.3}/LICENSE.txt +0 -0
  13. {scweet-5.2 → scweet-5.3}/MANIFEST.in +0 -0
  14. {scweet-5.2 → scweet-5.3}/Scweet/__init__.py +0 -0
  15. {scweet-5.2 → scweet-5.3}/Scweet/__main__.py +0 -0
  16. {scweet-5.2 → scweet-5.3}/Scweet/account_session.py +0 -0
  17. {scweet-5.2 → scweet-5.3}/Scweet/api_engine.py +0 -0
  18. {scweet-5.2 → scweet-5.3}/Scweet/async_tools.py +0 -0
  19. {scweet-5.2 → scweet-5.3}/Scweet/auth.py +0 -0
  20. {scweet-5.2 → scweet-5.3}/Scweet/config.py +0 -0
  21. {scweet-5.2 → scweet-5.3}/Scweet/cooldown.py +0 -0
  22. {scweet-5.2 → scweet-5.3}/Scweet/db.py +0 -0
  23. {scweet-5.2 → scweet-5.3}/Scweet/default_manifest.json +0 -0
  24. {scweet-5.2 → scweet-5.3}/Scweet/exceptions.py +0 -0
  25. {scweet-5.2 → scweet-5.3}/Scweet/http_utils.py +0 -0
  26. {scweet-5.2 → scweet-5.3}/Scweet/limiter.py +0 -0
  27. {scweet-5.2 → scweet-5.3}/Scweet/logging_config.py +0 -0
  28. {scweet-5.2 → scweet-5.3}/Scweet/manifest.py +0 -0
  29. {scweet-5.2 → scweet-5.3}/Scweet/models.py +0 -0
  30. {scweet-5.2 → scweet-5.3}/Scweet/outputs.py +0 -0
  31. {scweet-5.2 → scweet-5.3}/Scweet/query.py +0 -0
  32. {scweet-5.2 → scweet-5.3}/Scweet/queue.py +0 -0
  33. {scweet-5.2 → scweet-5.3}/Scweet/repos.py +0 -0
  34. {scweet-5.2 → scweet-5.3}/Scweet/resume.py +0 -0
  35. {scweet-5.2 → scweet-5.3}/Scweet/runner.py +0 -0
  36. {scweet-5.2 → scweet-5.3}/Scweet/scheduler.py +0 -0
  37. {scweet-5.2 → scweet-5.3}/Scweet/schema.py +0 -0
  38. {scweet-5.2 → scweet-5.3}/Scweet/storage.py +0 -0
  39. {scweet-5.2 → scweet-5.3}/Scweet/transaction.py +0 -0
  40. {scweet-5.2 → scweet-5.3}/Scweet/user_identity.py +0 -0
  41. {scweet-5.2 → scweet-5.3}/Scweet/utils.py +0 -0
  42. {scweet-5.2 → scweet-5.3}/Scweet.egg-info/SOURCES.txt +0 -0
  43. {scweet-5.2 → scweet-5.3}/Scweet.egg-info/dependency_links.txt +0 -0
  44. {scweet-5.2 → scweet-5.3}/Scweet.egg-info/entry_points.txt +0 -0
  45. {scweet-5.2 → scweet-5.3}/Scweet.egg-info/requires.txt +0 -0
  46. {scweet-5.2 → scweet-5.3}/Scweet.egg-info/top_level.txt +0 -0
  47. {scweet-5.2 → scweet-5.3}/pyproject.toml +0 -0
  48. {scweet-5.2 → scweet-5.3}/requirements.txt +0 -0
  49. {scweet-5.2 → scweet-5.3}/setup.cfg +0 -0
  50. {scweet-5.2 → scweet-5.3}/setup.py +0 -0
  51. {scweet-5.2 → scweet-5.3}/tests/test_accounts_repo.py +0 -0
  52. {scweet-5.2 → scweet-5.3}/tests/test_api_engine.py +0 -0
  53. {scweet-5.2 → scweet-5.3}/tests/test_auth.py +0 -0
  54. {scweet-5.2 → scweet-5.3}/tests/test_cli.py +0 -0
  55. {scweet-5.2 → scweet-5.3}/tests/test_client.py +0 -0
  56. {scweet-5.2 → scweet-5.3}/tests/test_config.py +0 -0
  57. {scweet-5.2 → scweet-5.3}/tests/test_cooldown.py +0 -0
  58. {scweet-5.2 → scweet-5.3}/tests/test_db.py +0 -0
  59. {scweet-5.2 → scweet-5.3}/tests/test_env_loaders.py +0 -0
  60. {scweet-5.2 → scweet-5.3}/tests/test_follows.py +0 -0
  61. {scweet-5.2 → scweet-5.3}/tests/test_integration.py +0 -0
  62. {scweet-5.2 → scweet-5.3}/tests/test_manifest.py +0 -0
  63. {scweet-5.2 → scweet-5.3}/tests/test_outputs.py +0 -0
  64. {scweet-5.2 → scweet-5.3}/tests/test_query.py +0 -0
  65. {scweet-5.2 → scweet-5.3}/tests/test_resume.py +0 -0
  66. {scweet-5.2 → scweet-5.3}/tests/test_runner.py +0 -0
  67. {scweet-5.2 → scweet-5.3}/tests/test_schema.py +0 -0
  68. {scweet-5.2 → scweet-5.3}/tests/test_session_builder.py +0 -0
  69. {scweet-5.2 → scweet-5.3}/tests/test_transaction.py +0 -0
  70. {scweet-5.2 → scweet-5.3}/tests/test_utils.py +0 -0
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [5.3.0] - 2026-04-14
6
+
7
+ ### Added
8
+
9
+ - **`manifest_scrape_on_init=` constructor shorthand** — pass `manifest_scrape_on_init=True` directly to `Scweet()` without needing `ScweetConfig`. Overrides the config value (same pattern as `proxy=`).
10
+ - **`--manifest-scrape-on-init` CLI flag** — scrape fresh GraphQL query IDs from X's `main.js` bundle on startup from the command line.
11
+ - **`save_name=` parameter** on `search`, `get_profile_tweets`, `get_followers`, `get_following`, and `get_user_info` — set a custom base filename for saved output (without extension).
12
+
13
+ ### Changed
14
+
15
+ - Documentation now marks `ct0` as optional in cookies examples — Scweet bootstraps it automatically from `auth_token`.
16
+ - Manifest scrape docs updated to reflect the new top-level constructor arg and CLI flag.
17
+
18
+ ---
19
+
5
20
  ## [5.2.0] - 2026-04-03
6
21
 
7
22
  ### Added
@@ -30,11 +30,13 @@ Create a `cookies.json` file:
30
30
  [
31
31
  {
32
32
  "username": "your_account",
33
- "cookies": { "auth_token": "...", "ct0": "..." }
33
+ "cookies": { "auth_token": "..." }
34
34
  }
35
35
  ]
36
36
  ```
37
37
 
38
+ `ct0` is optional — Scweet bootstraps it automatically from `auth_token`. You can include it if you have it:
39
+
38
40
  ```python
39
41
  s = Scweet(cookies_file="cookies.json")
40
42
  ```
@@ -43,8 +45,8 @@ For multiple accounts with per-account proxies (enables concurrent scraping and
43
45
 
44
46
  ```json
45
47
  [
46
- { "username": "account1", "cookies": { "auth_token": "...", "ct0": "..." }, "proxy": "http://user1:pass1@host1:port1" },
47
- { "username": "account2", "cookies": { "auth_token": "...", "ct0": "..." }, "proxy": "http://user2:pass2@host2:port2" }
48
+ { "username": "account1", "cookies": { "auth_token": "..." }, "proxy": "http://user1:pass1@host1:port1" },
49
+ { "username": "account2", "cookies": { "auth_token": "..." }, "proxy": "http://user2:pass2@host2:port2" }
48
50
  ]
49
51
  ```
50
52
 
@@ -211,6 +213,7 @@ tweets = s.search(
211
213
  | `resume` | `bool` | `False` | Resume from last checkpoint |
212
214
  | `save` | `bool` | `False` | Save results to disk |
213
215
  | `save_format` | `str` | config value | `"csv"`, `"json"`, or `"both"` |
216
+ | `save_name` | `str` | auto-generated | Base filename for saved output (without extension) |
214
217
 
215
218
  ### Async variant
216
219
 
@@ -245,6 +248,7 @@ tweets = s.get_profile_tweets(
245
248
  | `resume` | `bool` | `False` | Resume from last checkpoint |
246
249
  | `save` | `bool` | `False` | Save results to disk |
247
250
  | `save_format` | `str` | config value | `"csv"`, `"json"`, or `"both"` |
251
+ | `save_name` | `str` | auto-generated | Base filename for saved output (without extension) |
248
252
 
249
253
  Async: `await s.aget_profile_tweets(["elonmusk"], limit=100)`
250
254
 
@@ -269,6 +273,7 @@ users = s.get_following(["OpenAI"], limit=500)
269
273
  | `raw_json` | `bool` | `False` | Include full Twitter user payload under `raw` key |
270
274
  | `save` | `bool` | `False` | Save results to disk |
271
275
  | `save_format` | `str` | config value | `"csv"`, `"json"`, or `"both"` |
276
+ | `save_name` | `str` | auto-generated | Base filename for saved output (without extension) |
272
277
 
273
278
  ### raw_json option
274
279
 
@@ -297,6 +302,7 @@ profiles = s.get_user_info(["elonmusk", "OpenAI"])
297
302
  | `users` | `list[str]` | *required* | Usernames or profile URLs |
298
303
  | `save` | `bool` | `False` | Save results to disk |
299
304
  | `save_format` | `str` | config value | `"csv"`, `"json"`, or `"both"` |
305
+ | `save_name` | `str` | auto-generated | Base filename for saved output (without extension) |
300
306
 
301
307
  Async: `await s.aget_user_info(["elonmusk"])`
302
308
 
@@ -485,14 +491,17 @@ s = Scweet(
485
491
  Twitter/X rotates GraphQL query IDs periodically. When IDs go stale, requests return 404. Scweet ships with default IDs that work at release time, but you can auto-fetch fresh ones:
486
492
 
487
493
  ```python
488
- s = Scweet(
489
- cookies_file="cookies.json",
490
- config=ScweetConfig(manifest_scrape_on_init=True),
491
- )
494
+ s = Scweet(cookies_file="cookies.json", manifest_scrape_on_init=True)
492
495
  ```
493
496
 
494
497
  This fetches the current `main.js` bundle from X on init and extracts the latest query IDs. It adds a few seconds to startup but ensures your requests use current IDs.
495
498
 
499
+ From the CLI:
500
+
501
+ ```bash
502
+ scweet --auth-token TOKEN --manifest-scrape-on-init search "query" --limit 100
503
+ ```
504
+
496
505
  ---
497
506
 
498
507
  ## Account Management (ScweetDB)
@@ -629,7 +638,7 @@ The sync methods (`search`, `get_followers`, etc.) wrap their async counterparts
629
638
 
630
639
  ## Error Handling
631
640
 
632
- All Scweet methods raise exceptions on failure — there is no silent empty-result mode. Wrap calls in try/except to handle errors explicitly:
641
+ All Scweet methods raise exceptions on failure. Wrap calls in try/except to handle errors explicitly:
633
642
 
634
643
  ```python
635
644
  from Scweet import Scweet, AccountPoolExhausted, RateLimitError, AuthError, NetworkError, RunFailed
@@ -699,7 +708,7 @@ from Scweet import (
699
708
 
700
709
  **`RunFailed` / `NetworkError`**
701
710
  - Check your internet connection and proxy configuration
702
- - X may have rotated GraphQL query IDs — enable `manifest_scrape_on_init=True` to auto-fetch fresh ones
711
+ - X may have rotated GraphQL query IDs — pass `manifest_scrape_on_init=True` to `Scweet()` (or `--manifest-scrape-on-init` in the CLI) to auto-fetch fresh ones
703
712
  - 404 errors in logs mean stale query IDs (transient) — not bad auth
704
713
 
705
714
  ---
@@ -731,6 +740,7 @@ scweet [auth options] [config options] <subcommand> [subcommand options]
731
740
  |------|-------------|
732
741
  | `--proxy PROXY` | Proxy URL or JSON string |
733
742
  | `--concurrency N` | Worker concurrency (default: `5`) |
743
+ | `--manifest-scrape-on-init` | Scrape fresh query IDs from X's main.js on startup |
734
744
 
735
745
  ### Output options
736
746
 
scweet-5.3/PKG-INFO ADDED
@@ -0,0 +1,314 @@
1
+ Metadata-Version: 2.4
2
+ Name: Scweet
3
+ Version: 5.3
4
+ Summary: Scrape tweets, profiles, followers and more from Twitter/X — no API key needed
5
+ Home-page: https://github.com/Altimis/Scweet
6
+ Download-URL: https://github.com/Altimis/Scweet/archive/v5.3.tar.gz
7
+ Author: Yassine AIT JEDDI
8
+ Author-email: aitjeddiyassine@gmail.com
9
+ License: MIT
10
+ Keywords: twitter,x,scraper,twitter-scraper,x-scraper,tweets,tweet-search,twitter-search,followers,following,twitter-api-alternative,graphql,web-scraping,social-media,data-collection,python
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: python-dotenv
24
+ Requires-Dist: sqlmodel>=0.0.22
25
+ Requires-Dist: SQLAlchemy>=2.0
26
+ Requires-Dist: curl_cffi
27
+ Requires-Dist: XClientTransaction>=1.0.2
28
+ Requires-Dist: pydantic>=2.0
29
+ Dynamic: author
30
+ Dynamic: author-email
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: download-url
35
+ Dynamic: home-page
36
+ Dynamic: keywords
37
+ Dynamic: license
38
+ Dynamic: requires-dist
39
+ Dynamic: requires-python
40
+ Dynamic: summary
41
+
42
+ <h1 align="center">Scweet</h1>
43
+
44
+ <p align="center">
45
+ <strong>Scrape Twitter / X without the official API.</strong>
46
+ <br>
47
+ Hosted on Apify, or run locally with Python and CLI.
48
+ </p>
49
+
50
+ <p align="center">
51
+ <a href="https://apify.com/altimis/scweet?fpr=a40q9">
52
+ <img alt="Run on Apify" src="https://img.shields.io/badge/Run%20on-Apify-246DFF?logo=apify&logoColor=white">
53
+ </a>
54
+ <a href="#python-quickstart">
55
+ <img alt="Python Quickstart" src="https://img.shields.io/badge/Python-Quickstart-3776AB?logo=python&logoColor=white">
56
+ </a>
57
+ <a href="#cli">
58
+ <img alt="CLI Quickstart" src="https://img.shields.io/badge/CLI-Quickstart-111111?logo=gnu-bash&logoColor=white">
59
+ </a>
60
+ <a href="#documentation">
61
+ <img alt="Documentation" src="https://img.shields.io/badge/Docs-Full%20Reference-0A66C2">
62
+ </a>
63
+ </p>
64
+
65
+ <p align="center">
66
+ <a href="https://github.com/Altimis/Scweet/actions/workflows/tests.yml">
67
+ <img alt="Tests" src="https://github.com/Altimis/Scweet/actions/workflows/tests.yml/badge.svg">
68
+ </a>
69
+ <a href="https://pypi.org/project/scweet/">
70
+ <img alt="PyPI Version" src="https://img.shields.io/pypi/v/scweet.svg">
71
+ </a>
72
+ <a href="https://pepy.tech/projects/scweet">
73
+ <img alt="PyPI Downloads" src="https://static.pepy.tech/badge/scweet/month">
74
+ </a>
75
+ <a href="https://github.com/Altimis/scweet/blob/main/LICENSE">
76
+ <img alt="License" src="https://img.shields.io/github/license/Altimis/scweet">
77
+ </a>
78
+ <a href="https://apify.com/altimis/scweet">
79
+ <img alt="Scweet Actor Status" src="https://apify.com/actor-badge?actor=altimis/scweet">
80
+ </a>
81
+ </p>
82
+
83
+
84
+ ---
85
+ <p align="center">
86
+ <strong>Scrape tweets, profiles, followers and more from Twitter/X. Uses X's own web GraphQL API, authenticated with your browser cookies. No official API key or developer account needed.<strong>
87
+ </p>
88
+
89
+ ---
90
+
91
+ **What you can scrape:**
92
+ - [**Tweets**](DOCUMENTATION.md#search-api) — by keyword, hashtag, user, date range, engagement filters, language, location
93
+ - [**Profile timelines**](DOCUMENTATION.md#profile-tweets) — a user's full tweet history
94
+ - [**Followers / Following**](DOCUMENTATION.md#followers--following) — full account lists at scale
95
+ - [**User profiles**](DOCUMENTATION.md#user-info) — bio, follower count, verification status, and more
96
+
97
+ ---
98
+
99
+ ## Hosted — no setup needed
100
+
101
+ > [Run Scweet on Apify](https://apify.com/altimis/scweet?fpr=a40q9&fp_sid=jeb97) with no code, no cookies, and no account management. Free tier included.
102
+
103
+ > Running Scweet locally at any real volume usually means dedicated accounts and proxies. You can use a single proxy, a rotating proxy, or assign one per account. If you need a provider, [Webshare](https://www.webshare.io/?referral_code=kdgjcc09945q) works well. Disclosure: affiliate link.
104
+
105
+ ---
106
+
107
+ ## Quickstart
108
+
109
+ **1. Install**
110
+
111
+ ```bash
112
+ pip install -U Scweet
113
+ ```
114
+
115
+ **2. Get your `auth_token`**
116
+
117
+ Log into [x.com](https://x.com) → DevTools `F12` → **Application** → **Cookies** → `https://x.com` → copy the `auth_token` value.
118
+
119
+ Scweet auto-bootstraps the `ct0` CSRF token from `auth_token` alone — or use the [`cookies.json` format](#multiple-accounts--proxies) for multiple accounts at once.
120
+
121
+ **3. Scrape**
122
+
123
+ ```python
124
+ from Scweet import Scweet
125
+
126
+ # Credentials are stored in scweet_state.db automatically on first run
127
+ s = Scweet(auth_token="YOUR_AUTH_TOKEN", proxy="http://user:pass@host:port")
128
+
129
+ # Search tweets — save to CSV (save_format="json" or "both" also works)
130
+ tweets = s.search("bitcoin", since="2025-01-01", limit=500, save=True)
131
+
132
+ # Reuse provisioned accounts on subsequent runs — no credentials needed
133
+ s = Scweet(db_path="scweet_state.db")
134
+ tweets = s.search("ethereum", limit=500, save=True)
135
+ ```
136
+
137
+ > Always set `limit` — without it, scraping continues until your account's daily cap is hit.
138
+
139
+ > All methods have async variants: `asearch()`, `aget_profile_tweets()`, `aget_followers()`, etc.
140
+
141
+ ---
142
+
143
+ ## Common tasks
144
+
145
+ ### Search tweets
146
+
147
+ ```python
148
+ tweets = s.search(
149
+ "AI agents",
150
+ since="2026-01-01",
151
+ from_users=["elonmusk"],
152
+ min_likes=50,
153
+ limit=200,
154
+ save=True,
155
+ )
156
+ ```
157
+
158
+ ### Profile timeline
159
+
160
+ ```python
161
+ tweets = s.get_profile_tweets(["elonmusk"], limit=200)
162
+ ```
163
+
164
+ ### Followers / Following
165
+
166
+ ```python
167
+ followers = s.get_followers(["elonmusk"], limit=1000)
168
+ following = s.get_following(["elonmusk"], limit=1000)
169
+ ```
170
+
171
+ ### User profiles
172
+
173
+ ```python
174
+ profiles = s.get_user_info(["githubstatus", "elonmusk"])
175
+ ```
176
+
177
+ For the full list of supported search operators, see [twitter-advanced-search](https://github.com/igorbrigadir/twitter-advanced-search).
178
+
179
+ ---
180
+
181
+ ## CLI
182
+
183
+ ```bash
184
+ # Search with proxy, save to CSV
185
+ scweet --auth-token YOUR_AUTH_TOKEN --proxy http://user:pass@host:port \
186
+ search "bitcoin" --since 2025-01-01 --limit 500 --save
187
+
188
+ # Followers, saved as JSON
189
+ scweet --auth-token YOUR_AUTH_TOKEN \
190
+ followers elonmusk --limit 1000 --save --save-format json
191
+ ```
192
+
193
+ For multi-account runs, use `--cookies-file cookies.json`.
194
+
195
+ ---
196
+
197
+ ## Multiple accounts & proxies
198
+
199
+ For higher throughput and reduced ban risk, use multiple dedicated accounts with per-account proxies.
200
+
201
+ **`cookies.json` format:**
202
+
203
+ ```json
204
+ [
205
+ { "username": "acct1", "cookies": { "auth_token": "..." }, "proxy": "http://user1:pass1@host1:port1" },
206
+ { "username": "acct2", "cookies": { "auth_token": "..." }, "proxy": "http://user2:pass2@host2:port2" }
207
+ ]
208
+ ```
209
+
210
+ ```python
211
+ s = Scweet(cookies_file="cookies.json") # proxies are read from the file, one per account
212
+ ```
213
+
214
+ > **Never use your personal Twitter/X account for scraping.** Use dedicated accounts only.
215
+
216
+ ---
217
+
218
+ ## Why Scweet?
219
+
220
+ | | twint | snscrape | twscrape | **Scweet** |
221
+ |---|---|---|---|---|
222
+ | **Works in 2026** | ❌ unmaintained | ❌ broken | ✅ | ✅ |
223
+ | Cookie / token auth | ❌ | ❌ | ✅ | ✅ |
224
+ | Multi-account pooling | ❌ | ❌ | ✅ | ✅ |
225
+ | Proxy support | ❌ | ❌ | ✅ | ✅ |
226
+ | Resume interrupted scrapes | ❌ | ❌ | ❌ | ✅ |
227
+ | Built-in CSV / JSON output | ✅ | ✅ | ❌ | ✅ |
228
+ | Sync + async API | ❌ | ❌ | Async only | ✅ both |
229
+ | Hosted, no-setup option | ❌ | ❌ | ❌ | ✅ Apify |
230
+ | Active maintenance | ❌ | ❌ | ⚠️ | ✅ |
231
+
232
+ [twint](https://github.com/twintproject/twint) has been unmaintained since 2023. [snscrape](https://github.com/JustAnotherArchivist/snscrape) broke after X's backend changes. [twscrape](https://github.com/vladkens/twscrape) is the closest active alternative — worth knowing, but async-only, no built-in file output, and no resume support.
233
+
234
+ ---
235
+
236
+ ## Limitations
237
+
238
+ - Only publicly visible content is accessible — private/protected accounts are not supported
239
+ - Relies on undocumented X web endpoints; breakage is always possible after platform changes. Scweet can self-heal by scraping fresh query IDs and feature flags from X's `main.js` bundle at startup — pass `manifest_scrape_on_init=True` to enable:
240
+ ```python
241
+ s = Scweet(auth_token="...", manifest_scrape_on_init=True)
242
+ ```
243
+ - Cookies can expire and may need periodic refreshing
244
+ - A single account typically handles hundreds to a few thousand tweets per day before hitting rate limits; multi-account pooling scales proportionally
245
+ - Proxies and dedicated accounts are strongly recommended for anything beyond light testing
246
+ - Username/password login is not supported. X's anti-automation defenses make programmatic login unreliable and likely to trigger account locks. Scweet authenticates with browser cookies (`auth_token`) extracted from an active session instead
247
+
248
+ ---
249
+
250
+ ## Documentation
251
+
252
+ Full API reference, config options, structured search filters, async patterns, resume, proxies, and troubleshooting:
253
+
254
+ - [Account setup](DOCUMENTATION.md#account-setup)
255
+ - [Search API](DOCUMENTATION.md#search-api)
256
+ - [Profile tweets](DOCUMENTATION.md#profile-tweets)
257
+ - [Followers / Following](DOCUMENTATION.md#followers--following)
258
+ - [User info](DOCUMENTATION.md#user-info)
259
+ - [Saving results](DOCUMENTATION.md#saving-results)
260
+ - [Resume interrupted searches](DOCUMENTATION.md#resume-interrupted-searches)
261
+ - [Controlling limits](DOCUMENTATION.md#controlling-limits)
262
+ - [Configuration reference](DOCUMENTATION.md#configuration-reference)
263
+ - [Account management (ScweetDB)](DOCUMENTATION.md#account-management-scweetdb)
264
+ - [Async usage](DOCUMENTATION.md#async-usage)
265
+ - [Error handling](DOCUMENTATION.md#error-handling)
266
+ - [CLI reference](DOCUMENTATION.md#cli)
267
+
268
+ For advanced Twitter search operators, see [twitter-advanced-search](https://github.com/igorbrigadir/twitter-advanced-search).
269
+
270
+ ---
271
+
272
+ <details>
273
+ <summary><strong>FAQ</strong></summary>
274
+
275
+ <br>
276
+
277
+ **Does it work without an official Twitter API key?**
278
+ Yes. Scweet calls X's internal GraphQL API — the same one the web app uses. No developer account or API key required.
279
+
280
+ **Is it a replacement for twint or snscrape?**
281
+ Yes. Both are broken as of 2024–2025. Scweet uses a different, currently-working approach: cookies + GraphQL instead of legacy unauthenticated endpoints.
282
+
283
+ **How many tweets can I scrape?**
284
+ A single account typically handles hundreds to a few thousand tweets per day before hitting rate limits. Multi-account pooling scales this proportionally. The hosted Apify actor manages accounts and rate limits automatically.
285
+
286
+ **Will my account get banned?**
287
+ Never use your personal account — use dedicated accounts only. To reduce risk further: use **multiple accounts** (distributes load) and pair each with a **proxy** (prevents all requests from one IP).
288
+
289
+ **Does it work for private accounts?**
290
+ No. Only publicly visible content is accessible.
291
+
292
+ **Does it still work in 2025 / 2026?**
293
+ Yes — last verified working in March 2026 against X's current GraphQL API.
294
+
295
+ </details>
296
+
297
+ ---
298
+
299
+ ## Community
300
+
301
+ Have a question or want to share what you built with Scweet?
302
+ Open a thread in [**GitHub Discussions**](https://github.com/Altimis/Scweet/discussions).
303
+
304
+ **Found it useful? [Star the repo](https://github.com/Altimis/Scweet/stargazers)**
305
+
306
+ ---
307
+
308
+ ## Contributing
309
+
310
+ Bug reports, feature suggestions, and PRs are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
311
+
312
+ ---
313
+
314
+ *MIT License*