PHPackages                             klangch/laravel-ir-captcha - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. klangch/laravel-ir-captcha

ActiveLibrary

klangch/laravel-ir-captcha
==========================

Image rotation captcha library for Laravel 11/12

v1.0.5(9mo ago)0352↓50%MITPHPPHP ^8.1

Since Apr 28Pushed 9mo ago1 watchersCompare

[ Source](https://github.com/kleong153/laravel-ir-captcha)[ Packagist](https://packagist.org/packages/klangch/laravel-ir-captcha)[ Docs](https://github.com/kleong153/laravel-ir-captcha)[ RSS](/packages/klangch-laravel-ir-captcha/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (8)Versions (10)Used By (0)

Laravel IR Captcha
==================

[](#laravel-ir-captcha)

Laravel IR Captcha (Image Rotation Captcha) is a customizable image rotation CAPTCHA package for Laravel 11 and 12.

Features
--------

[](#features)

- Interactive, intuitive, and more user-friendly than classic text-based CAPTCHAs.
- Customizable UI and flexible configuration.
- No third-party services required. Everything are handled locally.

Preview
-------

[](#preview)

[![LaravelIRCaptcha Screenshot 1](https://private-user-images.githubusercontent.com/12734486/438350548-7baac265-c504-4d42-8efe-02a6fb7889cf.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzM4MjUzNTMsIm5iZiI6MTc3MzgyNTA1MywicGF0aCI6Ii8xMjczNDQ4Ni80MzgzNTA1NDgtN2JhYWMyNjUtYzUwNC00ZDQyLThlZmUtMDJhNmZiNzg4OWNmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAzMTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMzE4VDA5MTA1M1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAzOGRkNGMzYThhZmZiYmZjZjFkNzJiODM3ZTg1YzQ2NDgxYTNlNzdmYmNkY2IxYjgzYzZkOTRlNjAwN2I5MzEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.MSLjSr_I1lH8mGGbBnFgGM1-ZkFJZogDzl4I6Y7C7O0)](https://private-user-images.githubusercontent.com/12734486/438350548-7baac265-c504-4d42-8efe-02a6fb7889cf.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzM4MjUzNTMsIm5iZiI6MTc3MzgyNTA1MywicGF0aCI6Ii8xMjczNDQ4Ni80MzgzNTA1NDgtN2JhYWMyNjUtYzUwNC00ZDQyLThlZmUtMDJhNmZiNzg4OWNmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAzMTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMzE4VDA5MTA1M1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAzOGRkNGMzYThhZmZiYmZjZjFkNzJiODM3ZTg1YzQ2NDgxYTNlNzdmYmNkY2IxYjgzYzZkOTRlNjAwN2I5MzEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.MSLjSr_I1lH8mGGbBnFgGM1-ZkFJZogDzl4I6Y7C7O0)[![LaravelIRCaptcha Screenshot 2](https://private-user-images.githubusercontent.com/12734486/438350662-6c4efeb1-9903-4305-9de3-fb24f42353b3.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzM4MjUzNTMsIm5iZiI6MTc3MzgyNTA1MywicGF0aCI6Ii8xMjczNDQ4Ni80MzgzNTA2NjItNmM0ZWZlYjEtOTkwMy00MzA1LTlkZTMtZmIyNGY0MjM1M2IzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAzMTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMzE4VDA5MTA1M1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTU4ZDllOWYwMGI3ZDZhZTIzYTkzMjk5MzI1NTM2NjFjZDdlODM5MWY0YTRhOWVkNjJhY2U2OThhYmJiMGQ1MWImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.y6rJ0NgDKuOZiIG7aBULCxjSw6ie9d5pFF82QkgikIw)](https://private-user-images.githubusercontent.com/12734486/438350662-6c4efeb1-9903-4305-9de3-fb24f42353b3.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzM4MjUzNTMsIm5iZiI6MTc3MzgyNTA1MywicGF0aCI6Ii8xMjczNDQ4Ni80MzgzNTA2NjItNmM0ZWZlYjEtOTkwMy00MzA1LTlkZTMtZmIyNGY0MjM1M2IzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAzMTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMzE4VDA5MTA1M1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTU4ZDllOWYwMGI3ZDZhZTIzYTkzMjk5MzI1NTM2NjFjZDdlODM5MWY0YTRhOWVkNjJhY2U2OThhYmJiMGQ1MWImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.y6rJ0NgDKuOZiIG7aBULCxjSw6ie9d5pFF82QkgikIw)

    LaravelIRCaptcha.Demo.mp4    Installation
------------

[](#installation)

Make sure the PHP `gd` extension is installed and enabled.

Install with composer using following command:

```
composer require klangch/laravel-ir-captcha
```

Configuration
-------------

[](#configuration)

Publish configuration, view, localization files by using following command:

```
$ php artisan vendor:publish --provider="Klangch\LaravelIRCaptcha\LaravelIRCaptchaServiceProvider"
```

- `config/ir-captcha.php`
- `lang/vendor/ir-captcha/en/messages.php`
- `resoures/views/vendor/ir-captcha/irCaptcha.blade.php`

Usage
-----

[](#usage)

Show captcha in iframe

```

```

Listen for iframe's post message

```
window.addEventListener("message", (event) => {
    if (event.data && event.data.type === "irCaptcha" && event.data.status === "success") {
        // Get captcha token and set to input field
        document.querySelector("input[name='captcha_token']").value = event.data.captchaToken;

        // Continue form submission...
    }
});
```

### URL for iframe

[](#url-for-iframe)

```
// Get captcha URL with helper
ir_captcha()->iframeUrl();

// Get captcha URL with parent origin and dark theme
ir_captcha()->iframeUrl('https://[your_parent_origin].com', true);

// Or append parent origin and dark theme param manually
$url = ir_captcha()->iframeUrl() . '?parent_origin=https://[your_parent_origin].com&theme=dark';
```

or set dark theme dynamically in Laravel Blade + JS

```
// Get captcha URL with helper
let captchaUrl = "{{ ir_captcha()->iframeUrl() }}";

// Or without helper
let captchaUrl = "https://[your_captcha_domain].com/ir-captcha";

// Then append parent origin
captchaUrl += "?parent_origin=" + window.location.origin;

// Append theme
if (themeMode === "dark") {
    captchaUrl += "&theme=dark";
}

document.getElementById("captchaIframe").src = captchaUrl;
```

### Validate captcha token

[](#validate-captcha-token)

```
if (ir_captcha()->validateCaptchaToken($token) === true) {
    // Validation success
}
```

or by using Laravel validation rule:

```
use Illuminate\Support\Facades\Validator;
use Klangch\LaravelIRCaptcha\Rules\IRCaptcha;

$rules = [
    'captcha_token' => ['required', new IRCaptcha],
];

$validator = Validator::make($request->all(), $rules);
$validator->validate();
```

### Clear expired captcha files

[](#clear-expired-captcha-files)

Clear expired captcha files by using following command:

```
$ php artisan ir-captcha:clear-expired
```

You can set this command in cron job to regularly clear expired files.

⚠️ Note For Frontend Framework On Different Domains ⚠️
------------------------------------------------------

[](#️-note-for-frontend-framework-on-different-domains-️)

When using this package with frontend hosted on different domain (such as a Next.js app embedding captcha verification page via an iframe), there are a few important things to keep in mind:

### ⚠️ CSRF Exclusion

[](#️-csrf-exclusion)

CSRF protection may block requests due to cross-origin restrictions. To allow verification requests from the iframe to bypass CSRF validation, you can explicitly exclude the verification endpoint:

```
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    // ...

    $middleware->validateCsrfTokens(except: [
        'ir-captcha-verify',
    ]);
});
```

### ⚠️ Set Captcha Locale

[](#️-set-captcha-locale)

You can set the captcha's language by passing a locale code as a query string parameter, such as `_lang`. Then, use middleware to set the application's locale accordingly.

For example, in your HTML:

```

```

In your middleware, retrieve the `_lang` value and set the application locale:

```
public function handle(Request $request, Closure $next): Response
{
    $locale = $request->input('_lang', 'en');
    App::setLocale($locale);
    return $next($request);
}
```

For a complete working example, see the [Code Example](https://github.com/kleong153/laravel-ir-captcha-example) repository.

Code Example
------------

[](#code-example)

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance55

Moderate activity, may be stable

Popularity16

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~11 days

Recently: every ~19 days

Total

8

Last Release

297d ago

Major Versions

v0.1.0-alpha → v1.0.0-beta2025-04-29

### Community

Maintainers

![](https://www.gravatar.com/avatar/d7e3c66ab9fb034fd2a8b766fc0569064ba79270bcf64cc2e7575e98de2d7f36?d=identicon)[klangch](/maintainers/klangch)

---

Top Contributors

[![kleong153](https://avatars.githubusercontent.com/u/12734486?v=4)](https://github.com/kleong153 "kleong153 (15 commits)")

---

Tags

captchaimage-captchalaravellaravelcaptchaimage captchalaravel-captcha

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/klangch-laravel-ir-captcha/health.svg)

```
[![Health](https://phpackages.com/badges/klangch-laravel-ir-captcha/health.svg)](https://phpackages.com/packages/klangch-laravel-ir-captcha)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[laravel-zero/framework

The Laravel Zero Framework.

3371.4M369](/packages/laravel-zero-framework)[mckenziearts/laravel-notify

Flexible flash notifications for Laravel

1.7k1.1M5](/packages/mckenziearts-laravel-notify)[proengsoft/laravel-jsvalidation

Validate forms transparently with Javascript reusing your Laravel Validation Rules, Messages, and FormRequest

1.1k2.3M49](/packages/proengsoft-laravel-jsvalidation)[prologue/alerts

Prologue Alerts is a package that handles global site messages.

3486.1M30](/packages/prologue-alerts)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
