crawlforge-extractors 1.13.0 → 1.14.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.
package/README.md CHANGED
@@ -202,7 +202,7 @@ URL is reported in `reason` as a retired handle.
202
202
  ### Recognising a blocked page
203
203
 
204
204
  `documentVerdict` says what a fetched document is: the page, a bot-wall
205
- interstitial (Cloudflare, Amazon, DataDome, PerimeterX, Akamai, Vercel, AWS WAF), an
205
+ interstitial (Cloudflare, Amazon, DataDome, PerimeterX, Akamai, Vercel, AWS WAF, F5), an
206
206
  HTTP error page, an empty shell, a short error-titled placeholder, or a
207
207
  client-rendered app's own short error fallback under a normal title (quora.com's
208
208
  "Something went wrong. Wait a moment and try again."). A wall
package/index.d.ts CHANGED
@@ -308,7 +308,7 @@ export default TemplateRegistry;
308
308
 
309
309
  /** The bot-defence vendor whose interstitial a document is, and what gave it away. */
310
310
  export interface ChallengeVerdict {
311
- vendor: 'cloudflare' | 'amazon' | 'datadome' | 'perimeterx' | 'akamai' | 'vercel' | 'aws-waf';
311
+ vendor: 'cloudflare' | 'amazon' | 'datadome' | 'perimeterx' | 'akamai' | 'vercel' | 'aws-waf' | 'f5';
312
312
  evidence: string;
313
313
  }
314
314
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crawlforge-extractors",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Extraction logic shared by the CrawlForge MCP server and REST API — scrape templates, charset-correct capped body reading, structural fingerprinting, embedded-state extraction, and query-scoped highlights. One implementation, so the two surfaces cannot drift apart.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * blockedPage.js — decide whether a fetched document is the page or a wall.
3
3
  *
4
- * Cloudflare, Amazon, DataDome, PerimeterX, Akamai, Vercel and AWS WAF answer a
5
- * blocked request with HTTP 200 and a page of their own: a title, some prose
4
+ * Cloudflare, Amazon, DataDome, PerimeterX, Akamai, Vercel, AWS WAF and F5 answer
5
+ * a blocked request with a page of their own, often under HTTP 200: a title, some prose
6
6
  * and a challenge script. Reported as a successful scrape, that page hides
7
7
  * the block — producthunt.com came back "success:true, title: Just a
8
8
  * moment..." for three regression rounds (R10 Q1 → R15, 2026-09-04). The
@@ -68,6 +68,18 @@ const CHALLENGES = [
68
68
  vendor: 'aws-waf',
69
69
  markers: /window\.gokuProps\s*=/,
70
70
  evidence: 'an AWS WAF challenge interstitial'
71
+ },
72
+ {
73
+ // F5 BIG-IP ASM / Advanced WAF's default blocking page: the title
74
+ // "Request Rejected", one sentence and a support ID, about 250 bytes.
75
+ // walmart.com sent it with HTTP 444 to a plain fetch (2026-10-03). Its
76
+ // `server-timing: ak_p` header named Akamai, but walmart's normal 200s
77
+ // carry the same header (it is the CDN), so the page, not the header,
78
+ // says who refused the request.
79
+ vendor: 'f5',
80
+ title: /^request rejected$/i,
81
+ markers: /the requested url was rejected\.?\s*please consult with your administrator/i,
82
+ evidence: 'an F5 "Request Rejected" blocking page'
71
83
  }
72
84
  ];
73
85