curiosus-sdk
v0.2.3
Published
Technology detection SDK - detect any web technology from any URL
Maintainers
Readme
curiosus-sdk
Detect web technologies on any website. Currently supports Lenis smooth-scroll detection, with a plugin system for adding more technologies.
Install
npm install curiosus-sdk
# or
bun add curiosus-sdkTwo Modes
Lite (recommended for most use cases)
No Puppeteer. No browser. Just fetch. Works everywhere — browser, Node.js, Vercel, edge runtimes.
import { CuriosusLite } from "curiosus-sdk"
const curiosus = new CuriosusLite()
const { technologies } = await curiosus.detect("https://darkroom.engineering")
console.log(technologies)
// [{ name: "lenis", detected: true, version: null, method: "html-attributes (lite)" }]How it works:
- Fetches the page HTML
- Checks for Lenis CSS classes and
data-lenisattributes - Searches inline
<script>tags for Lenis markers - Fetches external JS files in parallel and searches them for Lenis code + version
~2-3 seconds per site. Detects ~80% of Lenis sites.
Full (maximum accuracy)
Uses Puppeteer to launch a real browser. Executes JavaScript, triggers scroll events, waits for hydration — catches everything.
import { Curiosus } from "curiosus-sdk"
const curiosus = new Curiosus()
const { technologies } = await curiosus.detect("https://darkroom.engineering")
console.log(technologies)
// [{ name: "lenis", detected: true, version: "1.3.17", method: "window.lenisVersion" }]How it works:
- Launches headless Chromium
- Navigates to the URL (3-tier fallback: networkidle2 > domcontentloaded > partial load)
- Scrolls through the page to trigger lazy-loaded scripts
- Dispatches scroll, wheel, and touch events to trigger library initialization
- Waits for React/Next.js hydration
- Runs 5 detection methods:
window.lenisVersionglobal (source of truth)window.Lenisconstructor checkwindow.lenisinstance check- HTML element attributes (
class="lenis",data-lenis) - Bundled script proximity search for version strings
~5-11 seconds per site. Requires Node.js.
Fast mode
Cuts wait times in half for interactive use:
const curiosus = new Curiosus({ fast: true })
const { technologies } = await curiosus.detect("https://darkroom.engineering")
// Same accuracy, ~5s instead of ~11sMultiple URLs
Both modes support batch detection:
// Lite — runs all in parallel
const curiosus = new CuriosusLite()
const results = await curiosus.detectMany([
"https://darkroom.engineering",
"https://linear.app",
"https://google.com",
])
// Full — sequential with browser lifecycle management
const curiosus = new Curiosus()
const results = await curiosus.detectMany([
"https://darkroom.engineering",
"https://linear.app",
])Which Mode Should I Use?
| Scenario | Mode | |----------|------| | Frontend / browser app | Lite | | Vercel / serverless | Lite | | Quick check from a script | Lite | | CI pipeline | Lite | | Need version detection | Full | | Need maximum accuracy | Full | | Batch analysis (hundreds of sites) | Full | | Sites with lazy-loaded Lenis | Full |
Configuration (Full mode)
const curiosus = new Curiosus({
// Reduce wait times for faster results (default: false)
fast: true,
// Per-site timeout in ms (default: 60000)
timeout: 30_000,
// Custom Chromium path (e.g., for Railway, Docker)
executablePath: "/usr/bin/chromium",
// Domains to skip
blacklistedDomains: ["example.com"],
// Custom logger
logger: {
log: (msg) => console.log(msg),
warn: (msg) => console.warn(msg),
error: (msg) => console.error(msg),
},
})Custom Detectors (Full mode)
Add your own technology detectors using the plugin interface:
import { Curiosus, type Detector, type TechnologyResult } from "curiosus-sdk"
import type { Page } from "puppeteer"
class GsapDetector implements Detector {
name = "gsap"
async detect(page: Page): Promise<TechnologyResult> {
const result = await page.evaluate(() => {
const w = window as unknown as Record<string, unknown>
const hasGsap = typeof w.gsap === "object" && w.gsap !== null
const version = hasGsap ? String((w.gsap as Record<string, unknown>).version || "") : null
return { hasGsap, version }
})
return {
name: this.name,
detected: result.hasGsap,
version: result.version,
method: result.hasGsap ? "window.gsap" : null,
}
}
}
const curiosus = new Curiosus()
curiosus.use(new GsapDetector())
const { technologies } = await curiosus.detect("https://some-site.com")
// [
// { name: "lenis", detected: true, version: "1.3.17", ... },
// { name: "gsap", detected: true, version: "3.12.5", ... }
// ]Response Shape
Both modes return the same structure:
interface DetectionResult {
url: string
technologies: TechnologyResult[]
}
interface TechnologyResult {
name: string // "lenis"
detected: boolean // true/false
version: string | null // "1.3.17" or null
method: string | null // detection method that matched
}License
MIT
