๐Ÿ“š API Reference

gif-captcha core library โ€” v1.0.0

Contents

Installation

npm

npm install gif-captcha
const gifCaptcha = require("gif-captcha");
// or
import gifCaptcha from "gif-captcha";

CDN (Browser)

<script src="https://unpkg.com/gif-captcha/src/index.js"></script>
<script>
  // Available as window.gifCaptcha
  const challenge = gifCaptcha.createChallenge({ ... });
</script>

Functions

sanitize(str) โ†’ string

Escape a string for safe insertion into innerHTML. Uses DOM-based escaping in browsers, regex-based escaping in Node.js.

ParamTypeDescription
strstringUntrusted input to escape
gifCaptcha.sanitize('<script>alert(1)</script>');
// โ†’ "&lt;script&gt;alert(1)&lt;/script&gt;"

gifCaptcha.sanitize('Hello "world" & friends');
// โ†’ 'Hello &quot;world&quot; &amp; friends'

createSanitizer() โ†’ { sanitize }

Create a standalone sanitizer instance. Useful when you need isolated sanitizers or want to avoid the global default.

const mySanitizer = gifCaptcha.createSanitizer();
mySanitizer.sanitize('<b>bold</b>');
// โ†’ "&lt;b&gt;bold&lt;/b&gt;"

loadGifWithRetry(container, challenge, attempt) โ†’ void

Load a GIF image into a DOM container with automatic retry on failure. On final failure, shows a fallback with a link to the source or a title hint. Browser-only.

ParamTypeDescription
containerHTMLElementDOM element to render into
challengeObjectChallenge object with title, gifUrl, and optional sourceUrl
attemptnumberCurrent attempt index (0-based, default 0)
const container = document.getElementById('captcha-gif');
gifCaptcha.loadGifWithRetry(container, {
  title: "Surprise Ending",
  gifUrl: "https://example.com/twist.gif",
  sourceUrl: "https://example.com/source"
});

textSimilarity(a, b) โ†’ number

Calculate word-level Jaccard similarity between two strings. Returns a score between 0 (no overlap) and 1 (identical words). Case-insensitive.

ParamTypeDescription
astringFirst string
bstringSecond string
gifCaptcha.textSimilarity("the cat sat on the mat", "the cat sat");
// โ†’ 0.833 (5/6 unique words overlap)

gifCaptcha.textSimilarity("hello world", "goodbye moon");
// โ†’ 0 (no shared words)

validateAnswer(userAnswer, expectedAnswer, options?) โ†’ { passed, score, hasKeywords }

Validate a user's CAPTCHA response against the expected answer using fuzzy text matching and optional keyword checks.

ParamTypeDescription
userAnswerstringThe user's typed response
expectedAnswerstringThe correct/expected answer
options.thresholdnumberMinimum similarity score to pass (default: 0.3)
options.requiredKeywordsstring[]Words that must appear in the answer (at least one)

Returns

FieldTypeDescription
passedbooleantrue if score โ‰ฅ threshold AND keywords matched
scorenumberJaccard similarity (0โ€“1)
hasKeywordsbooleanWhether at least one required keyword was found
gifCaptcha.validateAnswer(
  "the cat fell off the table",
  "the cat fell off the table unexpectedly"
);
// โ†’ { passed: true, score: 0.857, hasKeywords: true }

gifCaptcha.validateAnswer(
  "I cannot view animated images",
  "the cat fell off the table",
  { requiredKeywords: ["cat", "fell"] }
);
// โ†’ { passed: false, score: 0, hasKeywords: false }

createChallenge(opts) โ†’ Challenge throws Error

Create a structured CAPTCHA challenge object with validation.

ParamTypeRequiredDescription
opts.idnumber | stringโœ“Unique identifier
opts.titlestringHuman-readable title (defaults to "Challenge {id}")
opts.gifUrlstringโœ“URL of the GIF image
opts.sourceUrlstringOriginal source URL for attribution
opts.humanAnswerstringโœ“Expected human description
opts.aiAnswerstringTypical AI model response
opts.keywordsstring[]Keywords for validation
const challenge = gifCaptcha.createChallenge({
  id: 1,
  title: "Plot Twist",
  gifUrl: "https://media.tenor.com/twist.gif",
  humanAnswer: "Both fired trick guns with flags",
  aiAnswer: "I cannot view animated GIFs",
  keywords: ["trick", "guns", "flags"]
});

pickChallenges(pool, count?) โ†’ Challenge[]

Pick N random challenges from a pool without replacement, using Fisher-Yates shuffle. Does not modify the original array.

ParamTypeDescription
poolChallenge[]Array of challenge objects
countnumberNumber to pick (default: 5, max: pool length)
const selected = gifCaptcha.pickChallenges(allChallenges, 5);
// โ†’ 5 random challenges from the pool

installRoundRectPolyfill() โ†’ void

Install the roundRect polyfill on CanvasRenderingContext2D. No-op if already available or outside a browser. Used by analysis and simulator chart renderers.

gifCaptcha.installRoundRectPolyfill();
// Canvas roundRect() is now available in older browsers

Constants

NameValueDescription
GIF_MAX_RETRIES2Maximum retry attempts for failed GIF loads
GIF_RETRY_DELAY_MS1500Delay between retry attempts (ms)

GitHub ยท npm ยท Case Study ยท MIT License