Skip to content

Commit ee0e226

Browse files
authored
Merge pull request #168 from SentienceAPI/sync-extension-v2.7.0
Sync Extension: v2.7.0
2 parents 0ec2add + de7e339 commit ee0e226

File tree

3 files changed

+192
-32
lines changed

3 files changed

+192
-32
lines changed

sentience/extension/injected_api.js

Lines changed: 161 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,165 @@
1010
}
1111
return elements;
1212
}
13+
const CAPTCHA_TEXT_KEYWORDS = [ "verify you are human", "captcha", "human verification", "unusual traffic", "are you a robot", "security check", "prove you are human", "bot detection", "automated access" ], CAPTCHA_URL_HINTS = [ "captcha", "challenge", "verify" ], CAPTCHA_IFRAME_HINTS = {
14+
recaptcha: [ "recaptcha", "google.com/recaptcha" ],
15+
hcaptcha: [ "hcaptcha.com" ],
16+
turnstile: [ "challenges.cloudflare.com", "turnstile" ],
17+
arkose: [ "arkoselabs.com", "funcaptcha.com", "client-api.arkoselabs.com" ],
18+
awswaf: [ "amazonaws.com/captcha", "awswaf.com" ]
19+
}, CAPTCHA_SCRIPT_HINTS = {
20+
recaptcha: [ "recaptcha" ],
21+
hcaptcha: [ "hcaptcha" ],
22+
turnstile: [ "turnstile", "challenges.cloudflare.com" ],
23+
arkose: [ "arkoselabs", "funcaptcha" ],
24+
awswaf: [ "captcha.awswaf", "awswaf-captcha" ]
25+
}, CAPTCHA_CONTAINER_SELECTORS = [ {
26+
selector: ".g-recaptcha",
27+
provider: "recaptcha"
28+
}, {
29+
selector: "#g-recaptcha",
30+
provider: "recaptcha"
31+
}, {
32+
selector: "[data-sitekey]",
33+
provider: "unknown"
34+
}, {
35+
selector: 'iframe[title*="recaptcha" i]',
36+
provider: "recaptcha"
37+
}, {
38+
selector: ".h-captcha",
39+
provider: "hcaptcha"
40+
}, {
41+
selector: "#h-captcha",
42+
provider: "hcaptcha"
43+
}, {
44+
selector: 'iframe[title*="hcaptcha" i]',
45+
provider: "hcaptcha"
46+
}, {
47+
selector: ".cf-turnstile",
48+
provider: "turnstile"
49+
}, {
50+
selector: "[data-cf-turnstile-sitekey]",
51+
provider: "turnstile"
52+
}, {
53+
selector: 'iframe[src*="challenges.cloudflare.com"]',
54+
provider: "turnstile"
55+
}, {
56+
selector: "#FunCaptcha",
57+
provider: "arkose"
58+
}, {
59+
selector: ".funcaptcha",
60+
provider: "arkose"
61+
}, {
62+
selector: "[data-arkose-public-key]",
63+
provider: "arkose"
64+
}, {
65+
selector: 'iframe[src*="arkoselabs"]',
66+
provider: "arkose"
67+
}, {
68+
selector: "#captcha-container",
69+
provider: "awswaf"
70+
}, {
71+
selector: "[data-awswaf-captcha]",
72+
provider: "awswaf"
73+
}, {
74+
selector: 'iframe[title*="captcha" i]',
75+
provider: "unknown"
76+
} ];
77+
function addEvidence(list, value) {
78+
value && (list.length >= 5 || list.push(value));
79+
}
80+
function truncateText(text, maxLen) {
81+
return text ? text.length <= maxLen ? text : text.slice(0, maxLen) : "";
82+
}
83+
function matchHints(value, hints) {
84+
const lower = String(value || "").toLowerCase();
85+
return !!lower && hints.some(hint => lower.includes(hint));
86+
}
87+
function detectCaptcha() {
88+
const evidence = {
89+
text_hits: [],
90+
selector_hits: [],
91+
iframe_src_hits: [],
92+
url_hits: []
93+
};
94+
let hasIframeHit = !1, hasContainerHit = !1, hasScriptHit = !1, hasKeywordHit = !1, hasUrlHit = !1;
95+
const providerSignals = {
96+
recaptcha: 0,
97+
hcaptcha: 0,
98+
turnstile: 0,
99+
arkose: 0,
100+
awswaf: 0
101+
};
102+
try {
103+
const iframes = document.querySelectorAll("iframe");
104+
for (const iframe of iframes) {
105+
const src = iframe.getAttribute("src") || "", title = iframe.getAttribute("title") || "";
106+
if (src) for (const [provider, hints] of Object.entries(CAPTCHA_IFRAME_HINTS)) matchHints(src, hints) && (hasIframeHit = !0,
107+
providerSignals[provider] += 1, addEvidence(evidence.iframe_src_hits, truncateText(src, 120)));
108+
if (title && matchHints(title, [ "captcha", "recaptcha" ]) && (hasContainerHit = !0,
109+
addEvidence(evidence.selector_hits, 'iframe[title*="captcha"]')), evidence.iframe_src_hits.length >= 5) break;
110+
}
111+
} catch (e) {}
112+
try {
113+
const scripts = document.querySelectorAll("script[src]");
114+
for (const script of scripts) {
115+
const src = script.getAttribute("src") || "";
116+
if (src) {
117+
for (const [provider, hints] of Object.entries(CAPTCHA_SCRIPT_HINTS)) matchHints(src, hints) && (hasScriptHit = !0,
118+
providerSignals[provider] += 1, addEvidence(evidence.selector_hits, `script[src*="${hints[0]}"]`));
119+
if (evidence.selector_hits.length >= 5) break;
120+
}
121+
}
122+
} catch (e) {}
123+
for (const {selector: selector, provider: provider} of CAPTCHA_CONTAINER_SELECTORS) try {
124+
document.querySelector(selector) && (hasContainerHit = !0, addEvidence(evidence.selector_hits, selector),
125+
"unknown" !== provider && (providerSignals[provider] += 1));
126+
} catch (e) {}
127+
const textSnippet = function() {
128+
try {
129+
const candidates = document.querySelectorAll("h1, h2, h3, h4, p, label, button, form, div, span");
130+
let combined = "", count = 0;
131+
for (const node of candidates) {
132+
if (count >= 30 || combined.length >= 2e3) break;
133+
if (!node || "string" != typeof node.innerText) continue;
134+
if (!node.offsetWidth && !node.offsetHeight && !node.getClientRects().length) continue;
135+
const text = node.innerText.replace(/\s+/g, " ").trim();
136+
text && (combined += `${text} `, count += 1);
137+
}
138+
if (combined = combined.trim(), combined) return truncateText(combined, 2e3);
139+
} catch (e) {}
140+
try {
141+
let bodyText = document.body?.innerText || "";
142+
return !bodyText && document.body?.textContent && (bodyText = document.body.textContent),
143+
truncateText(bodyText.replace(/\s+/g, " ").trim(), 2e3);
144+
} catch (e) {
145+
return "";
146+
}
147+
}();
148+
if (textSnippet) {
149+
const lowerText = textSnippet.toLowerCase();
150+
for (const keyword of CAPTCHA_TEXT_KEYWORDS) lowerText.includes(keyword) && (hasKeywordHit = !0,
151+
addEvidence(evidence.text_hits, keyword));
152+
}
153+
try {
154+
const lowerUrl = (window.location?.href || "").toLowerCase();
155+
for (const hint of CAPTCHA_URL_HINTS) lowerUrl.includes(hint) && (hasUrlHit = !0,
156+
addEvidence(evidence.url_hits, hint));
157+
} catch (e) {}
158+
let confidence = 0;
159+
hasIframeHit && (confidence += .7), hasContainerHit && (confidence += .5), hasScriptHit && (confidence += .5),
160+
hasKeywordHit && (confidence += .3), hasUrlHit && (confidence += .2), confidence = Math.min(1, confidence),
161+
hasIframeHit && (confidence = Math.max(confidence, .8)), !hasKeywordHit || hasIframeHit || hasContainerHit || hasScriptHit || hasUrlHit || (confidence = Math.min(confidence, .4));
162+
const detected = confidence >= .7;
163+
let providerHint = null;
164+
return providerSignals.recaptcha > 0 ? providerHint = "recaptcha" : providerSignals.hcaptcha > 0 ? providerHint = "hcaptcha" : providerSignals.turnstile > 0 ? providerHint = "turnstile" : providerSignals.arkose > 0 ? providerHint = "arkose" : providerSignals.awswaf > 0 ? providerHint = "awswaf" : detected && (providerHint = "unknown"),
165+
{
166+
detected: detected,
167+
provider_hint: providerHint,
168+
confidence: confidence,
169+
evidence: evidence
170+
};
171+
}
13172
const DEFAULT_INFERENCE_CONFIG = {
14173
allowedTags: [ "label", "span", "div" ],
15174
allowedRoles: [],
@@ -691,7 +850,8 @@
691850
ready_state: document.readyState || null,
692851
quiet_ms: quietMs,
693852
node_count: nodeCount
694-
}
853+
},
854+
captcha: detectCaptcha()
695855
};
696856
} catch (e) {}
697857
return {

sentience/extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "Sentience Semantic Visual Grounding Extractor",
4-
"version": "2.6.0",
4+
"version": "2.7.0",
55
"description": "Extract semantic visual grounding data from web pages",
66
"permissions": ["activeTab", "scripting"],
77
"host_permissions": ["<all_urls>"],

sentience/extension/release.json

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
2-
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/277691523",
3-
"assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/277691523/assets",
4-
"upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/277691523/assets{?name,label}",
5-
"html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.6.0",
6-
"id": 277691523,
2+
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/277802850",
3+
"assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/277802850/assets",
4+
"upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/277802850/assets{?name,label}",
5+
"html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.7.0",
6+
"id": 277802850,
77
"author": {
88
"login": "rcholic",
99
"id": 135060,
@@ -25,21 +25,21 @@
2525
"user_view_type": "public",
2626
"site_admin": false
2727
},
28-
"node_id": "RE_kwDOQshiJ84QjTyD",
29-
"tag_name": "v2.6.0",
28+
"node_id": "RE_kwDOQshiJ84Qju9i",
29+
"tag_name": "v2.7.0",
3030
"target_commitish": "main",
31-
"name": "Release v2.6.0",
31+
"name": "Release v2.7.0",
3232
"draft": false,
3333
"immutable": false,
3434
"prerelease": false,
35-
"created_at": "2026-01-18T08:03:53Z",
36-
"updated_at": "2026-01-18T08:05:04Z",
37-
"published_at": "2026-01-18T08:04:24Z",
35+
"created_at": "2026-01-19T05:08:35Z",
36+
"updated_at": "2026-01-19T05:09:41Z",
37+
"published_at": "2026-01-19T05:09:31Z",
3838
"assets": [
3939
{
40-
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/342221644",
41-
"id": 342221644,
42-
"node_id": "RA_kwDOQshiJ84UZeNM",
40+
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/342599449",
41+
"id": 342599449,
42+
"node_id": "RA_kwDOQshiJ84Ua6cZ",
4343
"name": "extension-files.tar.gz",
4444
"label": "",
4545
"uploader": {
@@ -65,17 +65,17 @@
6565
},
6666
"content_type": "application/gzip",
6767
"state": "uploaded",
68-
"size": 77212,
69-
"digest": "sha256:82d79bfb011dbdf6ecd81b30689da13ee2045ac3df93534bee4b3c9ae3717670",
70-
"download_count": 2,
71-
"created_at": "2026-01-18T08:05:04Z",
72-
"updated_at": "2026-01-18T08:05:04Z",
73-
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.6.0/extension-files.tar.gz"
68+
"size": 79222,
69+
"digest": "sha256:e0cad96e20e539d62a4777f1c5baedb1c8bd02cd26a8e38f7c1b9c804325f068",
70+
"download_count": 0,
71+
"created_at": "2026-01-19T05:09:41Z",
72+
"updated_at": "2026-01-19T05:09:41Z",
73+
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.7.0/extension-files.tar.gz"
7474
},
7575
{
76-
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/342221645",
77-
"id": 342221645,
78-
"node_id": "RA_kwDOQshiJ84UZeNN",
76+
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/342599448",
77+
"id": 342599448,
78+
"node_id": "RA_kwDOQshiJ84Ua6cY",
7979
"name": "extension-package.zip",
8080
"label": "",
8181
"uploader": {
@@ -101,15 +101,15 @@
101101
},
102102
"content_type": "application/zip",
103103
"state": "uploaded",
104-
"size": 79031,
105-
"digest": "sha256:1f8fe71aeedf7143064afafadc19d83577932d125b66de3eb70e1f302173d172",
104+
"size": 80692,
105+
"digest": "sha256:83de4c4c54f401fc6404c27ef01a9205cf8e3566e81f62a7bc08f7103a2b0cc5",
106106
"download_count": 0,
107-
"created_at": "2026-01-18T08:05:04Z",
108-
"updated_at": "2026-01-18T08:05:04Z",
109-
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.6.0/extension-package.zip"
107+
"created_at": "2026-01-19T05:09:41Z",
108+
"updated_at": "2026-01-19T05:09:41Z",
109+
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.7.0/extension-package.zip"
110110
}
111111
],
112-
"tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.6.0",
113-
"zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.6.0",
112+
"tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.7.0",
113+
"zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.7.0",
114114
"body": ""
115115
}

0 commit comments

Comments
 (0)