is-antibot 1.5.0 → 1.6.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/LICENSE.md +0 -0
- package/README.md +3 -2
- package/package.json +18 -18
- package/src/index.js +16 -7
package/LICENSE.md
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ $ npm install is-antibot --save
|
|
|
60
60
|
|
|
61
61
|
## Usage
|
|
62
62
|
|
|
63
|
-
Just pass `headers`, `html`, and `
|
|
63
|
+
Just pass `headers`, `html`, `url`, and `statusCode` from any HTTP response:
|
|
64
64
|
|
|
65
65
|
```js
|
|
66
66
|
const isAntibot = require('is-antibot')
|
|
@@ -70,6 +70,7 @@ const html = await response.text()
|
|
|
70
70
|
|
|
71
71
|
const { detected, provider, detection } = isAntibot({
|
|
72
72
|
headers: response.headers,
|
|
73
|
+
statusCode: response.status,
|
|
73
74
|
html,
|
|
74
75
|
url: response.url
|
|
75
76
|
})
|
|
@@ -96,7 +97,7 @@ The library returns an object with the following properties:
|
|
|
96
97
|
|
|
97
98
|
- `detected` (boolean): Whether an antibot challenge was detected
|
|
98
99
|
- `provider` (string|null): The name of the detected provider (e.g., 'cloudflare', 'recaptcha')
|
|
99
|
-
- `detection` (string|null): Where the signal came from: `'headers'`, `'cookies'`, `'html'`, or `'
|
|
100
|
+
- `detection` (string|null): Where the signal came from: `'headers'`, `'cookies'`, `'html'`, `'url'`, or `'statusCode'`
|
|
100
101
|
|
|
101
102
|
## License
|
|
102
103
|
|
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.
|
|
5
|
+
"version": "1.6.0",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./src/index.js"
|
|
8
8
|
},
|
|
@@ -82,6 +82,22 @@
|
|
|
82
82
|
"files": [
|
|
83
83
|
"src"
|
|
84
84
|
],
|
|
85
|
+
"scripts": {
|
|
86
|
+
"clean": "rm -rf node_modules",
|
|
87
|
+
"contributors": "(npx git-authors-cli && npx finepack && git add package.json && git commit -m 'build: contributors' --no-verify) || true",
|
|
88
|
+
"coverage": "c8 report --reporter=text-lcov > coverage/lcov.info",
|
|
89
|
+
"lint": "standard",
|
|
90
|
+
"postrelease": "npm run release:tags && npm run release:github && (ci-publish || npm publish --access=public)",
|
|
91
|
+
"pretest": "npm run lint",
|
|
92
|
+
"release": "pnpm run release:version && pnpm run release:changelog && pnpm run release:commit && pnpm run release:tag",
|
|
93
|
+
"release:changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s",
|
|
94
|
+
"release:commit": "git add package.json CHANGELOG.md && git commit -m \"chore(release): $(node -p \"require('./package.json').version\")\"",
|
|
95
|
+
"release:github": "github-generate-release",
|
|
96
|
+
"release:tag": "git tag -a v$(node -p \"require('./package.json').version\") -m \"v$(node -p \"require('./package.json').version\")\"",
|
|
97
|
+
"release:tags": "git push origin HEAD:master --follow-tags",
|
|
98
|
+
"release:version": "standard-version --skip.changelog --skip.commit --skip.tag",
|
|
99
|
+
"test": "c8 ava"
|
|
100
|
+
},
|
|
85
101
|
"license": "MIT",
|
|
86
102
|
"ava": {
|
|
87
103
|
"files": [
|
|
@@ -111,21 +127,5 @@
|
|
|
111
127
|
"simple-git-hooks": {
|
|
112
128
|
"commit-msg": "npx commitlint --edit",
|
|
113
129
|
"pre-commit": "npx nano-staged"
|
|
114
|
-
},
|
|
115
|
-
"scripts": {
|
|
116
|
-
"clean": "rm -rf node_modules",
|
|
117
|
-
"contributors": "(npx git-authors-cli && npx finepack && git add package.json && git commit -m 'build: contributors' --no-verify) || true",
|
|
118
|
-
"coverage": "c8 report --reporter=text-lcov > coverage/lcov.info",
|
|
119
|
-
"lint": "standard",
|
|
120
|
-
"postrelease": "npm run release:tags && npm run release:github && (ci-publish || npm publish --access=public)",
|
|
121
|
-
"pretest": "npm run lint",
|
|
122
|
-
"release": "pnpm run release:version && pnpm run release:changelog && pnpm run release:commit && pnpm run release:tag",
|
|
123
|
-
"release:changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s",
|
|
124
|
-
"release:commit": "git add package.json CHANGELOG.md && git commit -m \"chore(release): $(node -p \"require('./package.json').version\")\"",
|
|
125
|
-
"release:github": "github-generate-release",
|
|
126
|
-
"release:tag": "git tag -a v$(node -p \"require('./package.json').version\") -m \"v$(node -p \"require('./package.json').version\")\"",
|
|
127
|
-
"release:tags": "git push origin HEAD:master --follow-tags",
|
|
128
|
-
"release:version": "standard-version --skip.changelog --skip.commit --skip.tag",
|
|
129
|
-
"test": "c8 ava"
|
|
130
130
|
}
|
|
131
|
-
}
|
|
131
|
+
}
|
package/src/index.js
CHANGED
|
@@ -8,7 +8,8 @@ const DETECTION = {
|
|
|
8
8
|
HEADERS: 'headers',
|
|
9
9
|
COOKIES: 'cookies',
|
|
10
10
|
HTML: 'html',
|
|
11
|
-
URL: 'url'
|
|
11
|
+
URL: 'url',
|
|
12
|
+
STATUS_CODE: 'statusCode'
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
const createGetHeader = headers =>
|
|
@@ -57,7 +58,7 @@ const getHeaderNames = headers =>
|
|
|
57
58
|
? Array.from(headers.keys())
|
|
58
59
|
: Object.keys(headers)
|
|
59
60
|
|
|
60
|
-
const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
61
|
+
const detect = ({ headers = {}, html = '', url = '', statusCode } = {}) => {
|
|
61
62
|
const getHeader = createGetHeader(headers)
|
|
62
63
|
const hasCookie = createHasCookie(headers)
|
|
63
64
|
const htmlHas = createTestPattern(html)
|
|
@@ -81,6 +82,9 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
81
82
|
|
|
82
83
|
const byUrl = provider => createResult(true, provider, DETECTION.URL)
|
|
83
84
|
|
|
85
|
+
const byStatusCode = provider =>
|
|
86
|
+
createResult(true, provider, DETECTION.STATUS_CODE)
|
|
87
|
+
|
|
84
88
|
// CloudFlare: Check for cf-mitigated header with 'challenge' value
|
|
85
89
|
// Official docs: https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/detect-response/
|
|
86
90
|
if (getHeader('cf-mitigated') === 'challenge') {
|
|
@@ -397,9 +401,9 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
397
401
|
return byHtml('reddit')
|
|
398
402
|
}
|
|
399
403
|
|
|
400
|
-
// LinkedIn:
|
|
401
|
-
if (
|
|
402
|
-
return
|
|
404
|
+
// LinkedIn: status 999 is LinkedIn's dedicated bot-detection response
|
|
405
|
+
if (parseUrl(url).domain === 'linkedin.com' && statusCode === 999) {
|
|
406
|
+
return byStatusCode('linkedin')
|
|
403
407
|
}
|
|
404
408
|
|
|
405
409
|
// YouTube: empty title pattern indicates a degraded response requiring BotGuard JS attestation
|
|
@@ -428,8 +432,13 @@ const detect = ({ headers = {}, html = '', url = '' } = {}) => {
|
|
|
428
432
|
}
|
|
429
433
|
|
|
430
434
|
const isAntibot = (input = {}) => {
|
|
431
|
-
const { headers, html, body, url } = input
|
|
432
|
-
return detect({
|
|
435
|
+
const { headers, html, body, url, statusCode, status } = input
|
|
436
|
+
return detect({
|
|
437
|
+
headers,
|
|
438
|
+
html: html || body,
|
|
439
|
+
url,
|
|
440
|
+
statusCode: statusCode ?? status
|
|
441
|
+
})
|
|
433
442
|
}
|
|
434
443
|
|
|
435
444
|
module.exports = isAntibot
|