is-antibot 2.0.2 → 2.0.4
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 +3 -2
- package/providers/reddit/failed.json +88 -0
- package/src/index.js +31 -7
- package/src/providers.json +19 -0
- package/src/schema.json +12 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "is-antibot",
|
|
3
3
|
"description": "Detect antibot protection from 30+ providers — Cloudflare, Akamai, DataDome, PerimeterX, Kasada, Imperva, reCAPTCHA, hCaptcha, Turnstile, and more.",
|
|
4
4
|
"homepage": "https://antibot.microlink.io/",
|
|
5
|
-
"version": "2.0.
|
|
5
|
+
"version": "2.0.4",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./src/index.js",
|
|
8
8
|
"./providers.json": "./src/providers.json",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@commitlint/cli": "latest",
|
|
74
74
|
"@commitlint/config-conventional": "latest",
|
|
75
|
-
"ava": "
|
|
75
|
+
"ava": "7",
|
|
76
76
|
"browser-sync": "latest",
|
|
77
77
|
"c8": "latest",
|
|
78
78
|
"ci-publish": "latest",
|
|
@@ -142,6 +142,7 @@
|
|
|
142
142
|
},
|
|
143
143
|
"nano-staged": {
|
|
144
144
|
"*.js": [
|
|
145
|
+
"npx -y @kikobeats/prettier-standard",
|
|
145
146
|
"standard --fix"
|
|
146
147
|
],
|
|
147
148
|
"package.json": [
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"log": {
|
|
3
|
+
"version": "1.2",
|
|
4
|
+
"creator": {
|
|
5
|
+
"name": "curl+node",
|
|
6
|
+
"version": "24.11.1"
|
|
7
|
+
},
|
|
8
|
+
"pages": [
|
|
9
|
+
{
|
|
10
|
+
"id": "page_1",
|
|
11
|
+
"title": "https://www.reddit.com/r/ProductivityApps/comments/1sr2f0w/nocal_is_a_calendar_app_that_turns_your_calendar/",
|
|
12
|
+
"startedDateTime": "2026-04-23T15:55:52.000Z",
|
|
13
|
+
"pageTimings": {
|
|
14
|
+
"onContentLoad": -1,
|
|
15
|
+
"onLoad": 150.0
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"entries": [
|
|
20
|
+
{
|
|
21
|
+
"pageref": "page_1",
|
|
22
|
+
"startedDateTime": "2026-04-23T15:55:52.000Z",
|
|
23
|
+
"time": 150.0,
|
|
24
|
+
"serverIPAddress": "",
|
|
25
|
+
"connection": "443",
|
|
26
|
+
"request": {
|
|
27
|
+
"method": "GET",
|
|
28
|
+
"url": "https://www.reddit.com/r/ProductivityApps/comments/1sr2f0w/nocal_is_a_calendar_app_that_turns_your_calendar/",
|
|
29
|
+
"httpVersion": "http/2.0",
|
|
30
|
+
"headers": [
|
|
31
|
+
{
|
|
32
|
+
"name": "host",
|
|
33
|
+
"value": "www.reddit.com"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "user-agent",
|
|
37
|
+
"value": "Slackbot 1.0 (+https://api.slack.com/robots)"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "accept",
|
|
41
|
+
"value": "*/*"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"queryString": [],
|
|
45
|
+
"cookies": [],
|
|
46
|
+
"headersSize": -1,
|
|
47
|
+
"bodySize": 0
|
|
48
|
+
},
|
|
49
|
+
"response": {
|
|
50
|
+
"status": 429,
|
|
51
|
+
"statusText": "Too Many Requests",
|
|
52
|
+
"httpVersion": "http/2.0",
|
|
53
|
+
"headers": [
|
|
54
|
+
{
|
|
55
|
+
"name": "x-ratelimit-remaining",
|
|
56
|
+
"value": "0.0"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "x-ratelimit-reset",
|
|
60
|
+
"value": "247"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "x-ratelimit-used",
|
|
64
|
+
"value": "45000"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "server",
|
|
68
|
+
"value": "snooserv"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "content-length",
|
|
72
|
+
"value": "0"
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"cookies": [],
|
|
76
|
+
"content": {
|
|
77
|
+
"size": 0,
|
|
78
|
+
"mimeType": "text/html",
|
|
79
|
+
"text": ""
|
|
80
|
+
},
|
|
81
|
+
"redirectURL": "",
|
|
82
|
+
"headersSize": -1,
|
|
83
|
+
"bodySize": -1
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/index.js
CHANGED
|
@@ -176,6 +176,7 @@ const createRegExp = (pattern, flags = '') => new RegExp(pattern, flags)
|
|
|
176
176
|
const createCompiledDetection = (detection, matches) => ({
|
|
177
177
|
type: detection.type,
|
|
178
178
|
domain: detection.domain,
|
|
179
|
+
domainWithoutSuffix: detection.domainWithoutSuffix,
|
|
179
180
|
matches
|
|
180
181
|
})
|
|
181
182
|
|
|
@@ -259,8 +260,19 @@ const DETECTION_COMPILERS = {
|
|
|
259
260
|
}
|
|
260
261
|
}
|
|
261
262
|
|
|
262
|
-
const compileDetection = detection =>
|
|
263
|
-
DETECTION_COMPILERS[detection.type](detection)
|
|
263
|
+
const compileDetection = detection => {
|
|
264
|
+
const compiled = DETECTION_COMPILERS[detection.type](detection)
|
|
265
|
+
const statusCodes = detection.statusCodes
|
|
266
|
+
if (!Array.isArray(statusCodes) || statusCodes.length === 0) {
|
|
267
|
+
return compiled
|
|
268
|
+
}
|
|
269
|
+
const allowed = new Set(statusCodes)
|
|
270
|
+
const innerMatches = compiled.matches
|
|
271
|
+
return {
|
|
272
|
+
...compiled,
|
|
273
|
+
matches: context => allowed.has(context.statusCode) && innerMatches(context)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
264
276
|
|
|
265
277
|
const compileProviders = ({ providers = [] } = {}) =>
|
|
266
278
|
providers.map(provider => ({
|
|
@@ -285,7 +297,13 @@ const detectWithProviders = (
|
|
|
285
297
|
const headerNames = getHeaderNames(headers)
|
|
286
298
|
const hasUrl = Boolean(url)
|
|
287
299
|
|
|
288
|
-
let
|
|
300
|
+
let parsedUrl
|
|
301
|
+
const getParsedUrl = () => {
|
|
302
|
+
if (!hasUrl) return null
|
|
303
|
+
if (!parsedUrl) parsedUrl = parseUrl(url)
|
|
304
|
+
return parsedUrl
|
|
305
|
+
}
|
|
306
|
+
|
|
289
307
|
const context = {
|
|
290
308
|
getHeader,
|
|
291
309
|
headerNames,
|
|
@@ -297,10 +315,16 @@ const detectWithProviders = (
|
|
|
297
315
|
|
|
298
316
|
for (const provider of compiledProviders) {
|
|
299
317
|
for (const detection of provider.detections) {
|
|
300
|
-
if (detection.domain) {
|
|
301
|
-
|
|
302
|
-
if (
|
|
303
|
-
if (detection.domain !== domain) continue
|
|
318
|
+
if (detection.domain || detection.domainWithoutSuffix) {
|
|
319
|
+
const parsed = getParsedUrl()
|
|
320
|
+
if (!parsed) continue
|
|
321
|
+
if (detection.domain && detection.domain !== parsed.domain) continue
|
|
322
|
+
if (
|
|
323
|
+
detection.domainWithoutSuffix &&
|
|
324
|
+
detection.domainWithoutSuffix !== parsed.domainWithoutSuffix
|
|
325
|
+
) {
|
|
326
|
+
continue
|
|
327
|
+
}
|
|
304
328
|
}
|
|
305
329
|
if (!detection.matches(context)) continue
|
|
306
330
|
return createResult(
|
package/src/providers.json
CHANGED
|
@@ -625,6 +625,9 @@
|
|
|
625
625
|
"rules": [
|
|
626
626
|
{
|
|
627
627
|
"status": 403
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
"status": 429
|
|
628
631
|
}
|
|
629
632
|
]
|
|
630
633
|
},
|
|
@@ -683,6 +686,22 @@
|
|
|
683
686
|
}
|
|
684
687
|
]
|
|
685
688
|
},
|
|
689
|
+
{
|
|
690
|
+
"name": "amazon",
|
|
691
|
+
"detections": [
|
|
692
|
+
{
|
|
693
|
+
"type": "headers",
|
|
694
|
+
"domainWithoutSuffix": "amazon",
|
|
695
|
+
"statusCodes": [500],
|
|
696
|
+
"rules": [
|
|
697
|
+
{
|
|
698
|
+
"header": "x-cache",
|
|
699
|
+
"startsWith": "Error from cloudfront"
|
|
700
|
+
}
|
|
701
|
+
]
|
|
702
|
+
}
|
|
703
|
+
]
|
|
704
|
+
},
|
|
686
705
|
{
|
|
687
706
|
"name": "anubis",
|
|
688
707
|
"detections": [
|
package/src/schema.json
CHANGED
|
@@ -57,6 +57,18 @@
|
|
|
57
57
|
"type": "string",
|
|
58
58
|
"description": "When set, this detection only applies if the request URL's registrable domain matches (e.g. 'reddit.com')."
|
|
59
59
|
},
|
|
60
|
+
"domainWithoutSuffix": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "When set, this detection only applies if the request URL's registrable domain without public suffix matches (e.g. 'amazon' for amazon.es, amazon.co.uk, amazon.com)."
|
|
63
|
+
},
|
|
64
|
+
"statusCodes": {
|
|
65
|
+
"type": "array",
|
|
66
|
+
"items": {
|
|
67
|
+
"type": "integer"
|
|
68
|
+
},
|
|
69
|
+
"minItems": 1,
|
|
70
|
+
"description": "When set, the detection matches only if the response status code equals one of these values (AND with the detection's rules)."
|
|
71
|
+
},
|
|
60
72
|
"rules": {
|
|
61
73
|
"type": "array",
|
|
62
74
|
"minItems": 1,
|