@the-convocation/twitter-scraper 0.21.1 → 0.22.0

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.
@@ -23,6 +23,62 @@ interface FetchTransformOptions {
23
23
  response: (response: Response) => Response | Promise<Response>;
24
24
  }
25
25
 
26
+ /**
27
+ * castle.ts - Local Castle.io v11 token generation for Twitter/X login flow.
28
+ *
29
+ * Ported from yubie-re/castleio-gen (Python, MIT license, archived May 2025)
30
+ * to TypeScript. Generates device fingerprint tokens required by Twitter's
31
+ * login flow to avoid error 399 ("suspicious activity").
32
+ *
33
+ * This generates Castle.io SDK v2.6.0 compatible tokens (version 11).
34
+ *
35
+ * Token structure overview:
36
+ * 1. Collect device/browser fingerprint data (3 parts)
37
+ * 2. Collect behavioral event data (mouse/keyboard/touch metrics)
38
+ * 3. Apply layered XOR encryption with timestamp and UUID keys
39
+ * 4. Prepend header (timestamp, SDK version, publisher key, UUID)
40
+ * 5. XXTEA-encrypt the entire payload
41
+ * 6. Base64URL-encode with version prefix and random XOR byte
42
+ */
43
+ /**
44
+ * Simulated browser environment values embedded in the fingerprint.
45
+ * These should match a realistic Chrome-on-Windows configuration.
46
+ *
47
+ * Users can provide a partial override via `ScraperOptions.experimental.browserProfile`
48
+ * to customize the fingerprint. Unspecified fields are randomized from realistic pools.
49
+ */
50
+ interface BrowserProfile {
51
+ locale: string;
52
+ language: string;
53
+ timezone: string;
54
+ screenWidth: number;
55
+ screenHeight: number;
56
+ /** Available screen width (excludes OS chrome like taskbars) */
57
+ availableWidth: number;
58
+ /** Available screen height (excludes OS chrome like taskbars) */
59
+ availableHeight: number;
60
+ /** WebGL ANGLE renderer string */
61
+ gpuRenderer: string;
62
+ /** Device memory in GB (encoded as value * 10) */
63
+ deviceMemoryGB: number;
64
+ /** Logical CPU core count */
65
+ hardwareConcurrency: number;
66
+ /** Screen color depth in bits */
67
+ colorDepth: number;
68
+ /** CSS device pixel ratio (encoded as value * 10) */
69
+ devicePixelRatio: number;
70
+ }
71
+ /**
72
+ * Generate a randomized browser profile by picking values from realistic pools.
73
+ *
74
+ * **Caution:** GPU renderer is NOT randomized because the canvas fingerprint
75
+ * hashes in the token are static and correspond to the DEFAULT_PROFILE GPU.
76
+ * Mismatching GPU + canvas hashes triggers Twitter 399 bot-detection errors.
77
+ * Screen resolution, device memory, and CPU cores are safe to randomize since
78
+ * they don't affect canvas rendering.
79
+ */
80
+ declare function randomizeBrowserProfile(): BrowserProfile;
81
+
26
82
  /**
27
83
  * Information about a rate-limiting event. Both the request and response
28
84
  * information are provided.
@@ -713,6 +769,18 @@ interface ScraperOptions {
713
769
  * Enables the generation of the `x-xp-forwarded-for` header on requests. This may resolve some errors.
714
770
  */
715
771
  xpff: boolean;
772
+ /**
773
+ * Delay in milliseconds between login flow steps, to mimic human-like timing.
774
+ * Without a delay, Twitter may flag rapid-fire requests as bot activity (error 399).
775
+ * Set to 0 to disable. Default is 1-3 seconds (average ~2s) with random jitter.
776
+ */
777
+ flowStepDelay?: number;
778
+ /**
779
+ * Override the browser profile used for Castle.io fingerprint token generation.
780
+ * Unspecified fields are randomized from realistic value pools.
781
+ * Set this if you want a consistent fingerprint or need to match specific hardware.
782
+ */
783
+ browserProfile?: Partial<BrowserProfile>;
716
784
  };
717
785
  }
718
786
  /**
@@ -724,6 +792,7 @@ declare class Scraper {
724
792
  private auth;
725
793
  private authTrends;
726
794
  private token;
795
+ private readonly subtaskHandlers;
727
796
  /**
728
797
  * Creates a new Scraper object.
729
798
  * - Scrapers maintain their own guest tokens for Twitter's internal API.
@@ -1002,4 +1071,4 @@ declare class Scraper {
1002
1071
  private handleResponse;
1003
1072
  }
1004
1073
 
1005
- export { ApiError, AuthenticationError, type DmConversation, type DmConversationResponse, type DmConversationTimeline, type DmInbox, type DmInboxResponse, type DmInboxTimelines, type DmMessage, type DmMessageData, type DmMessageEntities, type DmMessageEntry, type DmMessageUrl, type DmParticipant, type DmReaction, type DmStatus, type DmTimelineState, type DmWelcomeMessage, ErrorRateLimitStrategy, type FetchParameters, type FetchTransformOptions, type FlowSubtaskHandler, type FlowSubtaskHandlerApi, type FlowTokenResult, type FlowTokenResultError, type FlowTokenResultSuccess, type Mention, type Photo, type PlaceRaw, type Profile, type QueryProfilesResponse, type QueryTweetsResponse, type RateLimitEvent, type RateLimitStrategy, Scraper, type ScraperOptions, SearchMode, type Tweet, type TweetQuery, type TwitterApiErrorExtensions, type TwitterApiErrorPosition, type TwitterApiErrorRaw, type TwitterApiErrorTraceInfo, type TwitterUserAuthCredentials, type TwitterUserAuthFlowInitRequest, type TwitterUserAuthFlowRequest, type TwitterUserAuthFlowResponse, type TwitterUserAuthFlowSubtaskRequest, type Video, WaitingRateLimitStrategy };
1074
+ export { ApiError, AuthenticationError, type BrowserProfile, type DmConversation, type DmConversationResponse, type DmConversationTimeline, type DmInbox, type DmInboxResponse, type DmInboxTimelines, type DmMessage, type DmMessageData, type DmMessageEntities, type DmMessageEntry, type DmMessageUrl, type DmParticipant, type DmReaction, type DmStatus, type DmTimelineState, type DmWelcomeMessage, ErrorRateLimitStrategy, type FetchParameters, type FetchTransformOptions, type FlowSubtaskHandler, type FlowSubtaskHandlerApi, type FlowTokenResult, type FlowTokenResultError, type FlowTokenResultSuccess, type Mention, type Photo, type PlaceRaw, type Profile, type QueryProfilesResponse, type QueryTweetsResponse, type RateLimitEvent, type RateLimitStrategy, Scraper, type ScraperOptions, SearchMode, type Tweet, type TweetQuery, type TwitterApiErrorExtensions, type TwitterApiErrorPosition, type TwitterApiErrorRaw, type TwitterApiErrorTraceInfo, type TwitterUserAuthCredentials, type TwitterUserAuthFlowInitRequest, type TwitterUserAuthFlowRequest, type TwitterUserAuthFlowResponse, type TwitterUserAuthFlowSubtaskRequest, type Video, WaitingRateLimitStrategy, randomizeBrowserProfile };
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "scraper",
8
8
  "crawler"
9
9
  ],
10
- "version": "0.21.1",
10
+ "version": "0.22.0",
11
11
  "main": "dist/default/cjs/index.js",
12
12
  "types": "./dist/types/index.d.ts",
13
13
  "exports": {
@@ -41,6 +41,8 @@
41
41
  "docs:generate": "typedoc --options typedoc.json",
42
42
  "docs:deploy": "yarn docs:generate && gh-pages -d docs",
43
43
  "format": "prettier --write src/**/*.ts examples/**/*.{ts,js,tsx}",
44
+ "lint": "eslint src/",
45
+ "lint:fix": "eslint src/ --fix",
44
46
  "prepare": "husky install",
45
47
  "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --runInBand --forceExit"
46
48
  },
@@ -76,7 +78,7 @@
76
78
  "@types/tough-cookie": "^4.0.2",
77
79
  "@typescript-eslint/eslint-plugin": "^5.59.7",
78
80
  "@typescript-eslint/parser": "^5.59.7",
79
- "cycletls": "^2.0.4",
81
+ "cycletls": "^2.0.5",
80
82
  "cz-conventional-changelog": "^3.3.0",
81
83
  "dotenv": "^16.3.1",
82
84
  "esbuild": "^0.21.5",