JavaScript Image Rotation CAPTCHA

Rotated Image CAPTCHA Split Tux
Rotated Image CAPTCHA Split Tux

Live stream set for 2025-06-27 at 14:00:00 Eastern

Ask questions in the live chat about any programming or lifestyle topic.

This livestream will be on YouTube or you can watch below.


Image Rotation CAPTCHA: A Fun Way to Prevent Bots

Captchas are an essential tool for preventing bots and malicious scripts from interacting with your website or service. Traditional CAPTCHA methods, such as distorted text or simple math problems, can be frustrating for users and often fail to keep up with increasingly sophisticated bots.

A more engaging and user-friendly alternative is the Image Rotation CAPTCHA, where users are required to rotate a piece of an image back to its correct orientation. This CAPTCHA type provides both security and a more intuitive, interactive experience for users.

Verification Form

CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) involves challenges such as identifying distorted text or selecting images.

The CAPTCHA is used on web forms to prevent spam, malicious bots and other automated attacks.

A CAPTCHA presents a challenge that is relatively easy for humans to complete but difficult for bots to replicate.

In this tutorial, the rotation image-based CAPTCHA will be generated that users must type in the input box. An bitmap image will be split and the split portion of the image will need to be rotated.

How Does the Image Rotation CAPTCHA Work?

In a typical Image Rotation CAPTCHA, the process is simple yet effective:

  • Split the Image: An image is divided into several pieces.
  • Rotate One Piece: A random piece of the image is rotated by a certain angle.
  • Rotate Back: The user is tasked with rotating the piece back to its original position using a drag-to-rotate feature.
  • Validation: If the user rotates the piece correctly, the CAPTCHA is solved successfully. The system checks if the rotation is within a small tolerance (typically around 5 degrees).

This form of CAPTCHA is not only effective at blocking bots but also more engaging for users, as it involves an action (rotating an image) rather than a simple click or text input.

Why Choose Image Rotation CAPTCHA?

1. User-Friendly Interaction
Unlike text-based CAPTCHAs, which can often be misinterpreted by users or bots, the Image Rotation CAPTCHA offers a more intuitive approach. Rotating an image is a natural action that most users are familiar with, making it easier to complete.

2. Security
Since it requires real-time interaction (rotating a part of an image), it adds a layer of complexity that traditional CAPTCHA methods don’t offer. Bots that can easily solve text or simple math CAPTCHAs might struggle with rotating an image correctly, especially when it’s randomly rotated.

3. Visually Appealing
The Image Rotation CAPTCHA is visually engaging, providing a seamless and interactive experience that can be more aesthetically pleasing compared to traditional methods. It can enhance the user experience while adding an extra layer of security.

How to Implement an Image Rotation CAPTCHA

Implementing an Image Rotation CAPTCHA on your website is easier than you might think. Below is a simple example that you can customize to suit your needs. This implementation uses HTML, CSS, and JavaScript to create the interactive image rotation puzzle.

HTML CAPTCHA Form

<form class="image-captcha">
   <h3 class="middle">Form Image Rotation CAPTCHA</h3>
   <div class="middle captcha-container">
      <!-- Image pieces will be inserted here dynamically -->
   </div>
   <div class="captcha-buttons">
      <input type="submit" value="Submit" />
      <input type="reset" value="Reset" />
   </div>
   <output></output>
</form>
<script></script>

CSS CAPTCHA Form

.captcha-container {
    width: 300px;
    height: 300px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 2px;
    position: relative;
    border: 2px solid #ccc;
    overflow: hidden;
    background-color: #fff;
}

.captcha-piece {
    width: 100%;
    height: 100%;
    background-size: 200%;
    background-position: center;
    cursor: pointer;
    transition: transform 0.2s ease-in-out;
    user-select: none;  /* Disable text selection */
}

Rotated Image CAPTCHA Validator

         (() => {
            let captchaContainer = document.querySelector('.captcha-container');
            let output = document.querySelector('output');
            let imageUrl = 'Tux_05.avif'; // Replace with your image URL
            let rows = 2;
            let cols = 2;
            let pieces = [];
            let rotatedPieceIndex = Math.floor(Math.random() * (rows * cols)); // Randomly select a piece to rotate
            let isDragging = false;
            let initialAngle = 0;
            let currentAngle = 0;
            let initialX = 0;
            let initialY = 0;
            let draggedPiece = null;
            let tolerance = 5;
            let createPieces = () => {
                let pieceWidth = 300 / cols;
                let pieceHeight = 300 / rows;

                for (let row = 0; row < rows; row++) {
                    for (let col = 0; col < cols; col++) {
                        let piece = document.createElement('div');
                        piece.classList.add('captcha-piece');
                        piece.style.backgroundImage = `url(${imageUrl})`;
                        piece.style.backgroundPosition = `-${col * pieceWidth}px -${row * pieceHeight}px`;
                        piece.style.transform = `rotate(0deg)`; // Initial rotation is 0deg
                        piece.dataset.index = row * cols + col; // Store the piece index
                        piece.dataset.row = row;
                        piece.dataset.col = col;

                        // Add event listener to drag and rotate the piece
                        piece.addEventListener('mousedown', startDrag);

                        captchaContainer.appendChild(piece);
                        pieces.push(piece);
                    }
                }

                // Rotate the selected random piece by a random amount
                rotateRandomPiece();
            };
            let rotateRandomPiece = () => {
                let selectedPiece = pieces[rotatedPieceIndex];
                let randomRotation = (Math.random() * 180) + 45; // Random rotation between 45 and 180 degrees
                selectedPiece.style.transform = `rotate(${randomRotation}deg)`;
                selectedPiece.dataset.rotation = randomRotation;
            };
            let startDrag = (event) => {
                draggedPiece = event.target;
                isDragging = true;

                // Get initial mouse position and current rotation
                initialX = event.clientX;
                initialY = event.clientY;

                // Get current rotation angle of the piece
                initialAngle = getRotationAngle(draggedPiece);

                // Prevent text selection and default drag behavior
                event.preventDefault();

                // Add mousemove and mouseup listeners
                document.addEventListener('mousemove', dragPiece);
                document.addEventListener('mouseup', stopDrag);
            };
            let dragPiece = (event) => {
                if (!isDragging) return;

                // Get the movement of the mouse
                let deltaX = event.clientX - initialX;
                let deltaY = event.clientY - initialY;

                // Calculate the angle based on mouse movement
                let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);

                // Update the current rotation angle
                currentAngle = initialAngle + angle;

                // Apply the new rotation
                draggedPiece.style.transform = `rotate(${currentAngle}deg)`;
            };
            let stopDrag = () => {
                isDragging = false;

                // Remove mousemove and mouseup listeners
                document.removeEventListener('mousemove', dragPiece);
                document.removeEventListener('mouseup', stopDrag);

                // Update the rotation in the dataset
                draggedPiece.dataset.rotation = currentAngle;

                // Check if the piece is in the correct rotation
                let targetRotation = parseFloat(draggedPiece.dataset.rotation);
                if (Math.abs(currentAngle - targetRotation) <= tolerance) {
                    draggedPiece.style.border = '2px solid green'; // Mark as correctly rotated
                } else {
                    draggedPiece.style.border = '2px solid red'; // Incorrect rotation
                }
            };
            let getRotationAngle = (element) => {
                let matrix = window.getComputedStyle(element).transform;
                if (matrix === 'none') return 0;

                let values = matrix.split('(')[1].split(')')[0].split(',');
                let a = parseFloat(values[0]);
                let b = parseFloat(values[1]);
                let angle = Math.atan2(b, a) * (180 / Math.PI);
                return angle;
            };
            let ckCode = () => {
               isCorrect = true;
               pieces.forEach((piece) => {
                  if ( piece.hasAttribute('data-rotation') && !(Math.abs(parseFloat(piece.dataset.rotation)) <= tolerance) ) {
                     isCorrect = false;
                  }
               });
               if ( isCorrect ) {
               output.innerHTML = `<em class="pass">Validated</em>`;
               } else {
                  output.innerHTML = `<em class="fail">Failed</em>`;
               }
            };
            document.querySelector('form.captcha-validator').addEventListener('submit', (evt) => {
               evt.preventDefault();
               ckCode();
            });

            // Initialize the CAPTCHA
            createPieces();

         })();

This example splits the image into smaller pieces, rotates one piece randomly, and allows the user to rotate it back into place by dragging.

Screenshots

Image Rotation CAPTCHA Fail
Image Rotation CAPTCHA Failed Screenshot

Image Rotation CAPTCHA Pass
Image Rotation CAPTCHA Passed Screenshot

Screencast

Image Rotation CAPTCHA in action

Offering Programming Help for Implementation

If you need assistance with implementing an Image Rotation CAPTCHA on your website or application, I’m here to help! Whether you’re looking for a simple integration or a more advanced custom CAPTCHA solution, I can provide guidance on the following:

  • Custom CAPTCHA Designs: Tailoring the CAPTCHA to match your website’s theme and design.
  • Advanced Features: Adding additional layers of security, such as custom rotation angles or multi-step verifications.
  • Cross-Browser Support: Ensuring the CAPTCHA works flawlessly across all browsers and devices.
  • Backend Integration: Setting up server-side validation to confirm that the CAPTCHA was solved correctly before allowing form submissions.

Contact me for more information and a personalized quote!

About Edward

Edward is a software engineer, web developer, and author dedicated to helping people achieve their personal and professional goals through actionable advice and real-world tools.

As the author of impactful books including Learning JavaScript, Learning Python, Learning PHP and Mastering Blender Python API, Edward writes with a focus on personal growth, entrepreneurship, and practical success strategies. His work is designed to guide, motivate, and empower.

In addition to writing, Edward offers professional "full-stack development," "database design," "1-on-1 tutoring," "consulting sessions,", tailored to help you take the next step. Whether you are launching a business, developing a brand, or leveling up your mindset, Edward will be there to support you.

Edward also offers online courses designed to deepen your learning and accelerate your progress. Explore the programming on languages like JavaScript, Python and PHP to find the perfect fit for your journey.

📖 Explore His Books – Visit the Book Shop to grab your copies today.
💼 Need Support? – Learn more about Services and the ways to benefit from his expertise.
🎓 Ready to Learn? – Check out his Online Courses to turn your ideas into results.

Leave a Reply

Your email address will not be published. Required fields are marked *