captcha-canvas

A captcha generator by using skia-canvas module.


Keywords
captcha, skia-canvas, image, generator, wick, captcha-canvas, captcha-generator, node-canvas
License
Apache-2.0
Install
npm install captcha-canvas@3.2.3

Documentation

captcha-canvas

npm npm-bundle-size npm-downloads all-contributors

A powerful and highly customizable CAPTCHA generator for Node.js applications, built on top of the fast skia-canvas rendering engine. Generate secure, visually complex CAPTCHAs that are difficult for bots to solve while remaining accessible to humans.

Captcha Example

Table of Contents

Features

  • 🎨 Highly Customizable: Control every aspect including text, fonts, colors, backgrounds, rotation, skewing, and opacity
  • 🔒 Security Focused: Built-in trace lines, decoy characters, and visual distortions to prevent OCR attacks
  • ⚡ Dual API Design: Simple functions for quick generation or advanced classes for complex scenarios
  • 🖼️ Background Support: Add custom background images for enhanced visual complexity
  • 📱 Flexible Text: Support for multi-styled text segments and array-based configurations
  • 🚀 Performance: Async/sync generation methods with efficient canvas rendering
  • 📦 Lightweight: Minimal dependencies with peer dependency architecture
  • 🎯 TypeScript Ready: Full TypeScript support with comprehensive type definitions

Installation

Prerequisites

First, install the peer dependency skia-canvas:

npm install skia-canvas

Install captcha-canvas

npm install captcha-canvas

System Requirements

Quick Start

Generate a Simple CAPTCHA

const fs = require("fs");
const { createCaptchaSync } = require("captcha-canvas");

// Generate a 300x100 captcha
const { image, text } = createCaptchaSync(300, 100);

fs.writeFileSync("captcha.png", image);
console.log("Captcha text:", text);

Async Generation

const { createCaptcha } = require("captcha-canvas");

async function generateCaptcha() {
    const { image, text } = createCaptcha(300, 100);
    const buffer = await image;
    
    fs.writeFileSync("captcha.png", buffer);
    console.log("Captcha text:", text);
}

API Guide

Simple Functions

Perfect for quick CAPTCHA generation with minimal configuration.

createCaptcha(width, height, options?)

Generates a CAPTCHA asynchronously.

const { createCaptcha } = require("captcha-canvas");

const { image, text } = createCaptcha(400, 150, {
    captcha: {
        text: "HELLO",
        size: 60,
        color: "#2563eb"
    },
    decoy: {
        total: 30,
        opacity: 0.6
    },
    trace: {
        color: "#dc2626",
        size: 4
    }
});

createCaptchaSync(width, height, options?)

Generates a CAPTCHA synchronously (faster, but no background image support).

const { createCaptchaSync } = require("captcha-canvas");

const { image, text } = createCaptchaSync(400, 150, {
    captcha: {
        characters: 8,
        size: 50,
        color: "#059669"
    }
});

CaptchaGenerator Class

Provides a fluent interface for advanced CAPTCHA customization with method chaining.

Basic Usage

const { CaptchaGenerator } = require("captcha-canvas");

const captcha = new CaptchaGenerator()
    .setDimension(200, 500)
    .setCaptcha({
        text: "SECURE123",
        font: "Arial",
        size: 60,
        color: "#1f2937"
    })
    .setTrace({
        color: "#ef4444",
        size: 3
    })
    .setDecoy({
        total: 40,
        opacity: 0.7
    });

// Generate synchronously
const buffer = captcha.generateSync();
fs.writeFileSync("captcha.png", buffer);

// Or generate asynchronously (required for background images)
const asyncBuffer = await captcha.generate();

Method Chaining Examples

// Complete customization
const captcha = new CaptchaGenerator()
    .setDimension(250, 600)
    .setBackground("./background.jpg")
    .setCaptcha({
        text: "CUSTOM",
        font: "Comic Sans MS",
        size: 70,
        color: "#7c3aed",
        skew: true,
        rotate: 15,
        opacity: 0.9
    })
    .setTrace({
        color: "#dc2626",
        size: 5,
        opacity: 0.8
    })
    .setDecoy({
        color: "#6b7280",
        font: "Arial",
        size: 30,
        opacity: 0.4,
        total: 50
    });

const buffer = await captcha.generate();

Multi-Styled Text (Array Configuration)

Create CAPTCHAs with different styles for each character segment:

const captcha = new CaptchaGenerator()
    .setDimension(200, 400)
    .setCaptcha([
        { text: "AB", color: "red", size: 60, font: "Arial" },
        { text: "CD", color: "blue", size: 60, font: "Helvetica" },
        { text: "EF", color: "green", size: 60, font: "Times" }
    ]);

console.log(captcha.text); // "ABCDEF"

Captcha Class

Low-level class for fine-grained control over the rendering process.

const { Captcha } = require("captcha-canvas");

const captcha = new Captcha(600, 200, 8); // width, height, characters

// Build the captcha step by step
captcha.addDecoy({ total: 20, size: 40 });
captcha.drawCaptcha({ size: 50, color: "#1e40af" });
captcha.drawTrace({ color: "#dc2626", size: 4 });
captcha.addDecoy({ opacity: 0.3 }); // Add more decoys on top

// Get the result
const buffer = captcha.png;
console.log("Generated text:", captcha.text);

Configuration Options

Captcha Text Options

{
    text: "CUSTOM",        // Custom text (overrides characters)
    characters: 6,         // Number of random characters to generate
    font: "Arial",         // Font family
    size: 60,             // Font size in pixels
    color: "#000000",     // Text color (hex, rgb, or named)
    colors: ["#ff0000", "#00ff00"], // Array of colors (overrides color)
    skew: true,           // Apply random skewing
    rotate: 15,           // Max rotation angle in degrees
    opacity: 0.8          // Text opacity (0-1)
}

Trace Line Options

{
    color: "#ff0000",     // Line color
    size: 3,              // Line thickness
    opacity: 1.0          // Line opacity (0-1)
}

Decoy Characters Options

{
    color: "#cccccc",     // Decoy color
    font: "Arial",        // Decoy font
    size: 20,             // Decoy size
    opacity: 0.5,         // Decoy opacity (0-1)
    total: 30             // Number of decoy characters
}

Dimension Options

captcha.setDimension(height, width);
// Example: captcha.setDimension(150, 400);

Examples

Basic Web Server Integration

const express = require('express');
const { CaptchaGenerator } = require('captcha-canvas');

const app = express();

app.get('/captcha', async (req, res) => {
    const captcha = new CaptchaGenerator()
        .setDimension(100, 300)
        .setCaptcha({ characters: 6 });
    
    const buffer = captcha.generateSync();
    
    // Store captcha.text in session for verification
    req.session.captcha = captcha.text;
    
    res.setHeader('Content-Type', 'image/png');
    res.send(buffer);
});

app.post('/verify', (req, res) => {
    const userInput = req.body.captcha;
    const sessionCaptcha = req.session.captcha;
    
    if (userInput === sessionCaptcha) {
        res.json({ success: true });
    } else {
        res.json({ success: false });
    }
});

Custom Styling Examples

High Contrast CAPTCHA

const captcha = new CaptchaGenerator()
    .setDimension(120, 350)
    .setCaptcha({
        characters: 5,
        font: "Impact",
        size: 70,
        color: "#ffffff",
        skew: true,
        rotate: 20
    })
    .setTrace({
        color: "#ffffff",
        size: 2,
        opacity: 0.8
    })
    .setDecoy({
        color: "#666666",
        size: 25,
        opacity: 0.3,
        total: 20
    });

Colorful CAPTCHA

const captcha = new CaptchaGenerator()
    .setDimension(150, 400)
    .setCaptcha({
        characters: 6,
        font: "Comic Sans MS",
        size: 60,
        colors: ["#ff6b6b", "#4ecdc4", "#45b7d1", "#96ceb4", "#ffeaa7"],
        skew: true,
        rotate: 25
    })
    .setTrace({
        color: "#2d3436",
        size: 3
    });

Background Image CAPTCHA

const { resolveImage } = require('captcha-canvas');

async function createBackgroundCaptcha() {
    const backgroundImage = await resolveImage('./pattern.jpg');
    
    const captcha = new CaptchaGenerator()
        .setDimension(200, 500)
        .setBackground('./pattern.jpg')
        .setCaptcha({
            text: "SECURE",
            size: 80,
            color: "#ffffff",
            opacity: 0.9
        });
    
    return await captcha.generate();
}

Advanced Multi-Style Example

const captcha = new CaptchaGenerator()
    .setDimension(180, 500)
    .setCaptcha([
        { 
            text: "SEC", 
            color: "#e74c3c", 
            size: 70, 
            font: "Impact",
            rotate: 10 
        },
        { 
            text: "URE", 
            color: "#3498db", 
            size: 70, 
            font: "Arial Black",
            rotate: -10 
        }
    ])
    .setTrace({
        color: "#2c3e50",
        size: 4
    })
    .setDecoy({
        total: 35,
        opacity: 0.4
    });

console.log(captcha.text); // "SECURE"

Best Practices

Security Recommendations

  1. Always validate server-side: Never trust client-side CAPTCHA validation
  2. Use session storage: Store the correct answer in server-side sessions
  3. Implement rate limiting: Prevent brute force attacks
  4. Add expiration: Set time limits for CAPTCHA validity
  5. Use HTTPS: Protect CAPTCHA images and validation requests
// Example with expiration
app.get('/captcha', (req, res) => {
    const captcha = new CaptchaGenerator().setCaptcha({ characters: 6 });
    const buffer = captcha.generateSync();
    
    req.session.captcha = {
        text: captcha.text,
        expires: Date.now() + 300000 // 5 minutes
    };
    
    res.setHeader('Content-Type', 'image/png');
    res.send(buffer);
});

app.post('/verify', (req, res) => {
    const session = req.session.captcha;
    
    if (!session || Date.now() > session.expires) {
        return res.json({ success: false, error: 'CAPTCHA expired' });
    }
    
    const isValid = req.body.captcha === session.text;
    delete req.session.captcha; // Clear after use
    
    res.json({ success: isValid });
});

Performance Tips

  1. Use sync generation when possible: Faster for simple CAPTCHAs without backgrounds
  2. Cache background images: Load background images once and reuse
  3. Optimize dimensions: Larger images take more processing time
  4. Limit decoy characters: Too many decoys can impact performance

Accessibility Considerations

  1. Provide audio alternatives: Consider implementing audio CAPTCHAs
  2. Use sufficient contrast: Ensure text is readable for visually impaired users
  3. Offer refresh options: Allow users to generate new CAPTCHAs
  4. Consider alternative verification: Implement fallback verification methods

Troubleshooting

Common Issues

"Cannot find module 'skia-canvas'"

# Install the peer dependency
npm install skia-canvas

"Error: Canvas creation failed"

This usually indicates a problem with skia-canvas installation. Try:

# Reinstall skia-canvas
npm uninstall skia-canvas
npm install skia-canvas

# On some systems, you might need:
npm install skia-canvas --build-from-source

Background images not working

Ensure you're using the async generate() method:

// ❌ Wrong - sync method doesn't support backgrounds
captcha.setBackground('./bg.jpg');
const buffer = captcha.generateSync(); // Background ignored

// ✅ Correct - async method supports backgrounds
captcha.setBackground('./bg.jpg');
const buffer = await captcha.generate();

"Size of text and no. of characters is not matching"

This error occurs when you specify both text and characters with mismatched lengths:

// ❌ Wrong - text length (5) doesn't match characters (6)
captcha.setCaptcha({
    text: "HELLO",
    characters: 6
});

// ✅ Correct - let the library handle character count
captcha.setCaptcha({
    text: "HELLO"
});

// ✅ Or specify only character count for random text
captcha.setCaptcha({
    characters: 6
});

Platform-Specific Issues

Windows

  • Ensure Visual Studio Build Tools are installed
  • Use Node.js 14+ with npm 6+

macOS

  • Install Xcode Command Line Tools: xcode-select --install

Linux

API Reference

For complete API documentation with all methods, properties, and type definitions, visit:

📚 Full API Documentation

Quick Reference

Classes

  • CaptchaGenerator - High-level fluent interface
  • Captcha - Low-level canvas manipulation

Functions

  • createCaptcha(width, height, options?) - Async simple generation
  • createCaptchaSync(width, height, options?) - Sync simple generation
  • resolveImage(path) - Load images for backgrounds

Key Methods

  • .setDimension(height, width) - Set canvas size
  • .setCaptcha(options) - Configure text appearance
  • .setTrace(options) - Configure trace line
  • .setDecoy(options) - Configure decoy characters
  • .setBackground(image) - Set background image
  • .generate() - Generate async (supports backgrounds)
  • .generateSync() - Generate sync (faster, no backgrounds)

Contributing

We welcome contributions! Here's how you can help:

Development Setup

# Clone the repository
git clone https://github.com/Shashank3736/captcha-canvas.git
cd captcha-canvas

# Install dependencies
npm install

# Build the project
npm run build

# Run examples
npm run example

# Generate documentation
npm run docsgen

Contribution Guidelines

  1. Fork the repository and create a feature branch
  2. Write tests for new functionality
  3. Follow TypeScript best practices and existing code style
  4. Update documentation for API changes
  5. Test across platforms when possible
  6. Submit a pull request with a clear description

Reporting Issues

When reporting bugs, please include:

  • Node.js version
  • Operating system
  • captcha-canvas version
  • Minimal reproduction code
  • Error messages and stack traces

Open an issue at: GitHub Issues

License

This project is licensed under the Apache-2.0 License. See the LICENSE file for details.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Shashank

📆

TheDeadCraftPT

🐛

IchiiDev

🐛

Ikramullah

📖 💻

ryanhex53

💻

This project follows the all-contributors specification. Contributions of any kind welcome!