JSFiddle - React, Tailwind, and code Playground

HTML

<img id="moo" src="data:image/gif;base64,R0lGODlhAQABAPAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFMgABACwAAAAAAQABAAACAkwBACH5BAUyAAEALAAAAAABAAEAAAICRAEAOw==" width="2" height="20">

TypeScript

function getCaretGif(r: number, g: number, b: number) {      
    // original blinky gif data, courtesy of @mrkev, stringified.
    // the single non-transparent color in this gif is the first in the color palette,
    // so 0xD. the two strings below are gifBytes.substring(0, 0xD) and gifBytes.substring(0x10).
    // in other words, everything except the first color in the palette.
    const header = "GIF89a\u0001\u0000\u0001\u0000ð\u0000\u0000";
    const rest = "ÿÿÿ!ÿ\u000bNETSCAPE2.0\u0003\u0001\u0000\u0000\u0000!ù\u0004\u00052\u0000\u0001\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002L\u0001\u0000!ù\u0004\u00052\u0000\u0001\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;"
    
    // it actually made most sense to me to use a Uint8Array for this manipulation, but 
    // according to my shallow stack overflow and mdn dive, conversion both to 	
    // base64 looks to be a fair bunch of code and memcopying.
    //
    // thus, we break a bunch of rules and manipulate a gif by converting it into a string
    // and then patching a new string together.
    const gif = header
        + String.fromCharCode(r)
        + String.fromCharCode(g)
        + String.fromCharCode(b)
        + rest;
  	return "data:image/gif;base64," + window.btoa(gif);
  }


const moo = document.getElementById("moo");
setInterval(() => {
	const r = (Math.random() * 255) & 0xFF;
  const g = (Math.random() * 255) & 0xFF;
  const b = (Math.random() * 255) & 0xFF;
	moo.src = getCaretGif(r, g, b);
}, 2000);