is-antibot 1.3.4 → 1.3.5
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/package.json +1 -1
- package/src/index.js +44 -54
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "is-antibot",
|
|
3
3
|
"description": "Identify if a response is an antibot challenge from CloudFlare, Akamai, DataDome, Vercel, PerimeterX, Shape Security, and more, including CAPTCHA providers like reCAPTCHA and hCaptcha.",
|
|
4
4
|
"homepage": "https://github.com/microlinkhq/is-antibot",
|
|
5
|
-
"version": "1.3.
|
|
5
|
+
"version": "1.3.5",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./src/index.js"
|
|
8
8
|
},
|
package/src/index.js
CHANGED
|
@@ -66,7 +66,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// Akamai: Check for additional identifying headers (akamai-grn, x-akamai-session-info)
|
|
69
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/akamai.json
|
|
69
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-akamai.json
|
|
70
70
|
if (getHeader('akamai-grn') || getHeader('x-akamai-session-info')) {
|
|
71
71
|
return createResult(true, 'akamai')
|
|
72
72
|
}
|
|
@@ -88,7 +88,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// DataDome: Check for x-datadome or x-datadome-cid header presence
|
|
91
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/datadome.json
|
|
91
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-datadome.json
|
|
92
92
|
if (getHeader('x-datadome') || getHeader('x-datadome-cid')) {
|
|
93
93
|
return createResult(true, 'datadome')
|
|
94
94
|
}
|
|
@@ -99,13 +99,13 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// PerimeterX: Check for X-PX-Authorization header (primary indicator)
|
|
102
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/perimeterx.json
|
|
102
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-perimeterx.json
|
|
103
103
|
if (getHeader('x-px-authorization')) {
|
|
104
104
|
return createResult(true, 'perimeterx')
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// PerimeterX: Check for window._pxAppId, pxInit, or _pxAction in html
|
|
108
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/perimeterx.json
|
|
108
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-perimeterx.json
|
|
109
109
|
if (htmlHas('window._pxAppId') || htmlHas('pxInit') || htmlHas('_pxAction')) {
|
|
110
110
|
return createResult(true, 'perimeterx')
|
|
111
111
|
}
|
|
@@ -117,7 +117,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
117
117
|
|
|
118
118
|
// Shape Security: Check for dynamic header patterns x-[8chars]-[abcdfz]
|
|
119
119
|
// These headers use 8 random characters followed by suffixes like -a, -b, -c, -d, -f, or -z
|
|
120
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/shapesecurity.json
|
|
120
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-shapesecurity.json
|
|
121
121
|
const headerNames = Object.keys(headers)
|
|
122
122
|
for (const name of headerNames) {
|
|
123
123
|
if (/^x-[a-z0-9]{8}-[abcdfz]$/i.test(name)) {
|
|
@@ -126,37 +126,37 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// Shape Security: Check for 'shapesecurity' text in response html
|
|
129
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/shapesecurity.json
|
|
129
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-shapesecurity.json
|
|
130
130
|
if (htmlHas('shapesecurity')) {
|
|
131
131
|
return createResult(true, 'shapesecurity')
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
// Kasada: Check for x-kasada or x-kasada-challenge headers
|
|
135
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/kasada.json
|
|
135
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-kasada.json
|
|
136
136
|
if (getHeader('x-kasada') || getHeader('x-kasada-challenge')) {
|
|
137
137
|
return createResult(true, 'kasada')
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Kasada: Check for __kasada global object or kasada.js script in html
|
|
141
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/kasada.json
|
|
141
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-kasada.json
|
|
142
142
|
if (htmlHas('__kasada') || htmlHas('kasada.js')) {
|
|
143
143
|
return createResult(true, 'kasada')
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
// Imperva/Incapsula: Check for x-cdn header with 'Incapsula' value or x-iinfo header
|
|
147
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/incapsula.json
|
|
147
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-incapsula.json
|
|
148
148
|
if (getHeader('x-cdn') === 'Incapsula' || getHeader('x-iinfo')) {
|
|
149
149
|
return createResult(true, 'imperva')
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
// Imperva/Incapsula: Check for 'incapsula' or 'imperva' text in response html
|
|
153
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/incapsula.json
|
|
153
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-incapsula.json
|
|
154
154
|
if (htmlHas('incapsula') || htmlHas('imperva')) {
|
|
155
155
|
return createResult(true, 'imperva')
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// Imperva/Incapsula: incap_ses_, visid_incap_, or reese84 cookies
|
|
159
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/incapsula.json
|
|
159
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-incapsula.json
|
|
160
160
|
if (
|
|
161
161
|
hasCookie('incap_ses_') ||
|
|
162
162
|
hasCookie('visid_incap_') ||
|
|
@@ -166,7 +166,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// Reblaze: rbzid or rbzsessionid cookies
|
|
169
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/reblaze.json
|
|
169
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-reblaze.json
|
|
170
170
|
if (hasCookie('rbzid=') || hasCookie('rbzsessionid=')) {
|
|
171
171
|
return createResult(true, 'reblaze')
|
|
172
172
|
}
|
|
@@ -177,7 +177,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
// Cheq: Check for CheqSdk or cheqzone.com in html
|
|
180
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/cheq.json
|
|
180
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-cheq.json
|
|
181
181
|
if (htmlHas('CheqSdk') || htmlHas('cheqzone.com')) {
|
|
182
182
|
return createResult(true, 'cheq')
|
|
183
183
|
}
|
|
@@ -188,13 +188,13 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
// Sucuri: Check for 'sucuri' text in response html
|
|
191
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/sucuri.json
|
|
191
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-sucuri.json
|
|
192
192
|
if (htmlHas('sucuri')) {
|
|
193
193
|
return createResult(true, 'sucuri')
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
// ThreatMetrix: Check for 'ThreatMetrix' in html
|
|
197
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/threatmetrix.json
|
|
197
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-threatmetrix.json
|
|
198
198
|
if (htmlHas('ThreatMetrix')) {
|
|
199
199
|
return createResult(true, 'threatmetrix')
|
|
200
200
|
}
|
|
@@ -205,7 +205,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// Meetrics: Check for 'meetrics' text in response html
|
|
208
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/meetrics.json
|
|
208
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-meetrics.json
|
|
209
209
|
if (htmlHas('meetrics')) {
|
|
210
210
|
return createResult(true, 'meetrics')
|
|
211
211
|
}
|
|
@@ -216,7 +216,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
// Ocule: Check for ocule.co.uk in html
|
|
219
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/ocule.json
|
|
219
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-ocule.json
|
|
220
220
|
if (htmlHas('ocule.co.uk')) {
|
|
221
221
|
return createResult(true, 'ocule')
|
|
222
222
|
}
|
|
@@ -227,7 +227,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
// reCAPTCHA: Check for recaptcha/api, google.com/recaptcha, gstatic.com/recaptcha, or recaptcha.net in URL
|
|
230
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/recaptcha.json
|
|
230
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-recaptcha.json
|
|
231
231
|
if (
|
|
232
232
|
urlHas('recaptcha/api') ||
|
|
233
233
|
urlHas('google\\.com/recaptcha', true) ||
|
|
@@ -238,82 +238,72 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
// reCAPTCHA: Check for grecaptcha global object in html (primary JavaScript indicator)
|
|
241
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/recaptcha.json
|
|
241
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-recaptcha.json
|
|
242
242
|
if (htmlHas('grecaptcha')) {
|
|
243
243
|
return createResult(true, 'recaptcha')
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
// reCAPTCHA: Check for g-recaptcha container class in html
|
|
247
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/recaptcha.json
|
|
247
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-recaptcha.json
|
|
248
248
|
if (htmlHas('g-recaptcha')) {
|
|
249
249
|
return createResult(true, 'recaptcha')
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
// hCaptcha: Check for hcaptcha.com domain in URL
|
|
253
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/hcaptcha.json
|
|
253
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-hcaptcha.json
|
|
254
254
|
if (urlHas('hcaptcha\\.com', true)) {
|
|
255
255
|
return createResult(true, 'hcaptcha')
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
// hCaptcha: Check for hcaptcha
|
|
259
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/hcaptcha.json
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// hCaptcha: Check for h-captcha container class in html
|
|
265
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/hcaptcha.json#L51-L58
|
|
266
|
-
if (htmlHas('h-captcha')) {
|
|
258
|
+
// hCaptcha: Check for hcaptcha.com API domain or h-captcha container class in html
|
|
259
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-hcaptcha.json
|
|
260
|
+
// Note: bare 'hcaptcha' matches too broadly (could appear in articles discussing hCaptcha)
|
|
261
|
+
if (htmlHas('hcaptcha.com') || htmlHas('h-captcha')) {
|
|
267
262
|
return createResult(true, 'hcaptcha')
|
|
268
263
|
}
|
|
269
264
|
|
|
270
265
|
// FunCaptcha (Arkose Labs): Check for arkoselabs.com or funcaptcha in URL
|
|
271
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/funcaptcha.json
|
|
266
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-funcaptcha.json
|
|
272
267
|
if (urlHas('arkoselabs\\.com', true) || urlHas('funcaptcha')) {
|
|
273
268
|
return createResult(true, 'funcaptcha')
|
|
274
269
|
}
|
|
275
270
|
|
|
276
|
-
// FunCaptcha (Arkose Labs): Check for
|
|
277
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/funcaptcha.json
|
|
278
|
-
|
|
271
|
+
// FunCaptcha (Arkose Labs): Check for arkoselabs.com API domain or funcaptcha in html
|
|
272
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-funcaptcha.json
|
|
273
|
+
// Note: bare 'arkose' matches too broadly (e.g. Facebook bundles Arkose SDK for login without blocking content)
|
|
274
|
+
if (htmlHas('arkoselabs.com') || htmlHas('funcaptcha')) {
|
|
279
275
|
return createResult(true, 'funcaptcha')
|
|
280
276
|
}
|
|
281
277
|
|
|
282
278
|
// GeeTest: Check for geetest.com domain in URL
|
|
283
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/geetest.json
|
|
279
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-geetest.json
|
|
284
280
|
if (urlHas('geetest\\.com', true)) {
|
|
285
281
|
return createResult(true, 'geetest')
|
|
286
282
|
}
|
|
287
283
|
|
|
288
284
|
// GeeTest: Check for geetest object or text in html
|
|
289
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/geetest.json
|
|
285
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-geetest.json
|
|
286
|
+
// Note: bare 'gt.js' removed (too generic, any script named gt.js would match)
|
|
290
287
|
if (htmlHas('geetest')) {
|
|
291
288
|
return createResult(true, 'geetest')
|
|
292
289
|
}
|
|
293
290
|
|
|
294
|
-
// GeeTest: Check for gt.js script in html
|
|
295
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/geetest.json#L53-L60
|
|
296
|
-
if (htmlHas('gt.js')) {
|
|
297
|
-
return createResult(true, 'geetest')
|
|
298
|
-
}
|
|
299
|
-
|
|
300
291
|
// Cloudflare Turnstile: Check for challenges.cloudflare.com/turnstile in URL
|
|
301
292
|
if (urlHas('challenges\\.cloudflare\\.com/turnstile', true)) {
|
|
302
293
|
return createResult(true, 'cloudflare-turnstile')
|
|
303
294
|
}
|
|
304
295
|
|
|
305
|
-
// Cloudflare Turnstile: Check for cf-turnstile class in html
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (htmlHas('turnstile')) {
|
|
296
|
+
// Cloudflare Turnstile: Check for cf-turnstile class or turnstile API script in html
|
|
297
|
+
// Note: bare 'turnstile' matches too broadly (common English word)
|
|
298
|
+
if (
|
|
299
|
+
htmlHas('cf-turnstile') ||
|
|
300
|
+
htmlHas('challenges.cloudflare.com/turnstile')
|
|
301
|
+
) {
|
|
312
302
|
return createResult(true, 'cloudflare-turnstile')
|
|
313
303
|
}
|
|
314
304
|
|
|
315
305
|
// Friendly Captcha: Check for friendlycaptcha.com in URL
|
|
316
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/friendlycaptcha.json
|
|
306
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-friendlycaptcha.json
|
|
317
307
|
if (urlHas('friendlycaptcha\\.com', true)) {
|
|
318
308
|
return createResult(true, 'friendly-captcha')
|
|
319
309
|
}
|
|
@@ -324,7 +314,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
324
314
|
}
|
|
325
315
|
|
|
326
316
|
// Captcha.eu: Check for captcha.eu in URL
|
|
327
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/captchaeu.json
|
|
317
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-captchaeu.json
|
|
328
318
|
if (urlHas('captcha\\.eu', true)) {
|
|
329
319
|
return createResult(true, 'captcha-eu')
|
|
330
320
|
}
|
|
@@ -335,7 +325,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
335
325
|
}
|
|
336
326
|
|
|
337
327
|
// QCloud Captcha (Tencent): Check for turing.captcha.qcloud.com in URL
|
|
338
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/qcloud.json
|
|
328
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-qcloud.json
|
|
339
329
|
if (urlHas('turing\\.captcha\\.qcloud\\.com', true)) {
|
|
340
330
|
return createResult(true, 'qcloud-captcha')
|
|
341
331
|
}
|
|
@@ -346,7 +336,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
346
336
|
}
|
|
347
337
|
|
|
348
338
|
// AliExpress CAPTCHA: Check for punish?x5secdata in URL
|
|
349
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/aliexpress.json
|
|
339
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/captcha/detect-aliexpress.json
|
|
350
340
|
if (urlHas('punish\\?x5secdata', true)) {
|
|
351
341
|
return createResult(true, 'aliexpress-captcha')
|
|
352
342
|
}
|
|
@@ -368,7 +358,7 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
368
358
|
}
|
|
369
359
|
|
|
370
360
|
// AWS WAF: Check for x-amzn-waf-action or x-amzn-requestid headers
|
|
371
|
-
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/aws-waf.json
|
|
361
|
+
// Reference: https://github.com/scrapfly/Antibot-Detector/blob/main/detectors/antibot/detect-aws-waf.json
|
|
372
362
|
if (getHeader('x-amzn-waf-action') || getHeader('x-amzn-requestid')) {
|
|
373
363
|
return createResult(true, 'aws-waf')
|
|
374
364
|
}
|