yahew.comThe custom cursor
yahew.com

The custom cursor

Best viewed on a desktop, with a mouse. This whole page is about something a website did to your pointer, so a touch screen has nothing here to take over. The game falls back to an on-screen pad, but the joke does not survive it.

Internet Explorer 6, 2001. You could draw the pointer, but the number deciding where it clicked lived inside the file, invisible, and nothing made it agree with the picture.

PlayA page has taken your pointer. Close the windows before nine pile up.
Mouse

Round 1.

cleanup.exe

Run over.

Scroll it into viewSCORE 000000ROUND 1 of 4cursorCLOCK 14.0OPEN 0 of 9BEST 0

no cursor yet

Close the windows. Nine open at once and you are done. Click the desktop to give it the keyboard, then M switches the arrow keys on and Escape ends the run.

cursors-4u.com

This is the part that was about the web. You did not install these. Somebody pasted one line into their page and every visitor got it, whether they wanted it or not.

<style>* {cursor: url('sparkle.cur'), auto !important;}</style>

Hover any one to wear it right now. Click it to keep it, and the game below will use it. 694 cursors, 226 of them animated.

wearing: the normal pointer

The 45 at the end with names like SmoothHourglass and blackwait are the real 2006 and 2007 sets by Vlasta, chrisyco and Squiddy22, CC BY. The other 649 are rehosted from cursors-4u.com, which has been handing out paste-in cursors since 2004 and states no licence we can rely on. They are here credited and linked, not claimed.

A browser will not decode .ani at all, so the animated Windows cursors of the era, the spinning hourglass and the working-in-background pointer, cannot be worn on a web page even now. Thirteen of the files fetched for this plate were .ani and none of them survived that test. The animated ones you can wear here are animated .webp, which is a modern format doing an old job.

ReadWhat just happened, and why the web stopped doing it. Drag any window by its title bar.
Mouse Properties

That one was telling the truth.

Round 1 handed the browser a real Windows cursor file, generated for this page, whose header puts the click point at 2,2. The arrow's tip is drawn at 2,2. Nothing was corrected and nothing was simulated: your clicks landed on the pixel you were pointing at because the number in the file happened to agree with the picture.

That agreement was never guaranteed by anything. It was a choice the author made, or did not.

Mouse Properties

Your clicks landed here.

That is a real pointing hand, drawn by Squiddy22 in 2007, 4,286 bytes. Its own header puts the click point at (0,0). The first pixel it actually draws is at (5,0). You were aiming with a fingertip that was five pixels away from the thing doing the clicking, and nothing on screen could have told you.

CSS could not even express a hotspot until the CSS3 UI working draft of 3 July 2003. For the five years before that, the number could only come from inside the file.

Decoding the file...

Display Properties

Nobody agreed.

Precision Select is one single Windows role. The three sets in this corpus that ship one, all published in 2006 and 2007, declare (16,16), (14,14) and (11,11). Three sets, three answers, and no two of them agree. There was no convention to look up, so everybody picked a number.

DeclaredSetByPublished
(16,16)Advanced CrosshairAndy1612007
(14,14)Plain Blackchrisyco2006
(11,11)Antialiased ClassicVlasta2006

Round 3 used (16,16), which twelve of the thirteen Advanced Crosshair files declare regardless of what they draw. Across the 62 files in those four period sets, 19 declare (0,0), and two of those draw their first pixel somewhere else: Linkselect-cursor.cur and Crossout-cursor.cur, both Squiddy22, both starting at (5,0). Two files in sixty-two is a small number and it is the exact one round 2 makes you fight.

The full corpus behind this plate is 141 files, but four of its eight sets were uploaded to rw-designer in July and August 2026, one of them the day before this page was built. Those sets declare four further Precision Select hotspots and carry most of the mismatches. They are measured in corpus/hotspot-table.txt and deliberately kept off this page, because a 2026 upload is not evidence about 2006.

Security

The band at the top was not us being nice.

On 20 November 2006 somebody filed a Firefox bug showing that a big, mostly transparent cursor with a moving hotspot could be used to fake the address bar. Mozilla picked a limit on 24 January 2007 and landed it on trunk the next day: 128 by 128. Firefox 67, on 21 May 2019, started dropping any cursor over 32 px that would leave the content viewport. Blink and WebKit both still carry the 128, and the 32 px near-chrome rule belongs to Gecko and Blink.

The URL bar can be spoofed by using a large, mostly transparent custom cursor image and dynamically modifying the hotspot coordinates as per CSS3 specs (http://www.w3.org/TR/css3-ui/#cursor). Cursors will overflow outside of the browser content area. Affects Firefox 1.5 and later.

Bugzilla 361298, comment 0, filed 2006-11-20

That last sentence is the whole of round 4. A cursor overflows the content area, so the browser now takes it back near its own furniture. The darker band across the top of that desktop is this page recreating the clampdown on purpose, because the thing that made round 4 playable is the thing that killed the toy. Take the big cursor to the very top of your browser window and watch it disappear without our help.

Two files, two bytes apart

Same arrow, twice

These two files are ours, generated from scratch by curfmt/make-cur.py, 4,286 bytes each, identical except for the two hotspot fields at offsets 10 and 12, one byte different in each. Pick one, then try to click the small square. Nothing here corrects or intercepts your click: the browser reads the number out of the file and puts the click where the file says. The only script involved swaps which file the box is wearing and marks the spot the click landed on.

Pick a cursor, then click the square.

Same drawn arrow, both times. In the second one the click lands 19 px right and 23 px down from the tip you are aiming with, in your own browser, with nothing running.

The seven real files on this page

Hover a tile to wear it

Seven genuine Windows cursor binaries, published 2006 and 2007, rehosted here rather than hotlinked. The bit depth, the declared hotspot and the first drawn pixel are parsed out of each file's own bytes; the author, the date and the licence come from its gallery page, because no .cur carries any of those. The last column is where the artwork actually starts, which is not usually the number in the header.

squiddy22-linkselect.curSquiddy22, 2007-05-0532 bpp, declares (0,0), draws from 5,0source set
squiddy22-black-arrow.curSquiddy22, 2007-05-0532 bpp, declares (0,0), draws from 0,0source set
vlasta-smooth-arrow.curVlasta, 2006-07-0532 bpp, declares (2,2), draws from 3,1source set
vlasta-smooth-hand.curVlasta, 2006-07-1532 bpp, declares (9,2), draws from 9,1source set
vlasta-precision.curVlasta, 2006-07-1532 bpp, declares (11,11), draws from 12,2source set
chrisyco-black-arrow.curchrisyco, 2006-07-228 bpp, declares (15,4), draws from n/asource set
chrisyco-black-precision.curchrisyco, 2006-07-228 bpp, declares (14,14), draws from n/asource set

Two of the seven are 8 bits per pixel, a 256-colour palette cursor. The other five are 32bpp with an alpha channel. That split is a period detail sitting inside the files themselves.

cometcursor.com

The decoration phoned home

Comet Cursor was a browser plugin whose whole job was repainting the pointer. Its own demo page from April 2000 names the roles it could take over, in the markup, and there are four of them: Normal, Hyperlink, Ibeam, Wait. Windows carries fifteen such roles, by the count in Cursors-4U's own cursor editor documentation, which is a commercial site's product copy rather than a Microsoft source. A binary plugin, on two plugin APIs, to address a quarter of the vocabulary.

All other versions of the Comet Cursor contact our servers to record logs of cursor impressions using a GUID (Globally Unique IDentifier).

Comet Systems privacy policy, Wayback capture 2000-05-11

Quoted, not paraphrased, and not stretched into a bigger claim than it makes. No install count is given here because none of the captured pages is a source for one.

About that click sound

One oscillator, no plugin

In 1999 a button that made a clicking noise cost you an invisible EMBED in the body with HIDDEN, NAME and MASTERSOUND set, a plugin the visitor had to already have, and a browser sniff wrapped around the whole thing. Netscape's own JavaScript guide names "create buttons that make clicking noises" as the use case, and states that a MASTERSOUND attribute must accompany any NAME.

The sounds on this page are the real Windows 98 .wav files: DING when a window closes, the CHORD error when a click misses, TADA when a run is cleared. They are Microsoft's, rehosted from a public archive of them and credited below rather than claimed. The one-second tick is still a single oscillator, because Windows never shipped a ticking clock to borrow.

Field marks: how to spot one
  • The art never fills the square. Across the 47 period files here that carry an alpha channel, the median drawn box is 17 by 20 pixels inside a 32 by 32 canvas, so there is dead ground down the right edge and along the bottom of nearly every one. A period pointer floats in the top left of its own tile with room to spare.
  • The hotspot is invisible, and it is not always the tip. Of the 62 cursor files here from four sets published in 2006 and 2007, 19 declare their click point at (0,0), and two of them draw nothing there at all: Linkselect-cursor.cur and Crossout-cursor.cur, both Squiddy22, both declaring (0,0) while their first opaque pixel sits at (5,0). The number lives at bytes +4 and +6 of a 16-byte directory entry, in the two slots the icon format calls wPlanes and wBitCount. No Microsoft document in the folder behind this plate describes that repurposing; it is verified by parsing files, not by reading a spec.
  • Hard edges, or feathered ones, and you can see which. Fifteen of those 62 period files are 8 bits per pixel, a 256-colour palette with no alpha channel at all, so the outline cuts straight against whatever is behind it. The other 47 are 32bpp with alpha and feather at the edge. Two of the seven cursors shipped on this page are palette files; the other five are not.
  • Only .CUR and .ANI. Internet Explorer 6's own MSDN page puts it in one sentence: .CUR and .ANI are the only supported cursor types. No GIF, no PNG, no JPEG. All 62 period files measured here are 32 by 32, as are the other 79 in the corpus, and that single size is what the restriction looks like on a screen.
  • If it is moving, it is an .ANI. A .cur holds one still image; animation needs the other format, a RIFF container of numbered frames with the frame rate written beside them in jiffies, at 1/60 of a second each. Seventeen of the 62 period files here are .ani, and they cluster: all thirteen Advanced Crosshair files animate, and four of the eighteen Antialiased Classic ones do, while the other two sets have none.
What it solved, and what took it

A pointer is the one thing on a screen that is always yours to look at and never yours to change. A stranger's web page can still change it, which is the entire appeal, and it is why free-cursor sites existed at all and why Comet Cursor could ship a browser plugin whose whole job was repainting four of the operating system's fifteen cursor roles. What went away is not the property, it is the reach: from 2007 onward browsers put a ceiling on the size, and from 2019 they stopped letting the thing anywhere near their own furniture.

Every rule you write still has to end in a keyword. cursor: url("hand.cur"), pointer and nothing less: MDN calls the keyword a single mandatory value, so there is no way to name a custom cursor without also naming the operating system cursor it falls back to. The grammar itself keeps a way back to the OS, which turns out to have been the point.

What took the rest was not taste. It was that the invisible number could lie, and people worked out what to do with that. The clampdown is datable and it runs one bug at a time from 2007 to 2020, and it ends with WebKit and Blink both carrying the 128 and with Gecko and Blink both dropping anything over 32 px that reaches the browser's own UI.

CSS UI 3 answers the security questionnaire on itself. Does this specification allow an origin some measure of control over a user agent's native UI? Yes.

The problem it solved: your pointer belonged to the operating system, and for a while your page could borrow it. Then somebody pointed the borrowed thing at the address bar, and that was the end of it.

Back to the directory.

Source note
Where everything on this page came from, and what is a recreation

Chrome. Every bevel, colour and metric on this page is a value read out of 98.css v0.1.21 (MIT, Copyright 2020 Jordan Scales), captured at reference/1-decoration/custom-cursor/98css/. The window frames, buttons, close boxes and sunken fields are its numbers, including the 16 by 14 close box that the game is built around. 98.css ships no taskbar, so the strip along the bottom of the desktop is a recreation built from the same bevel and type rules, not a reproduction of anything Microsoft drew. The bevel order lifted from it is four one-pixel edges in a fixed sequence: white then #dfdfdf on the top left, #808080 then #0a0a0a on the bottom right, with an outer shadow of #0a0a0a rather than black, and a press swaps the pairs without moving anything a pixel. That is a field mark of the window chrome, not of the cursor, so it lives here rather than in the panel above. No Microsoft artwork, sound or font binary is in this repository. The desktop is #008080, which is the W3C and HTML 4.01 named colour teal; that is this plate's choice of ground and not a claim about what Windows 98 shipped with. One consequence of quoting 98.css exactly: its title-bar text is white at 11px bold, and against the light end of the active gradient (#1084d0) that measures 4.0:1, while against the inactive one (#b5b5b5) it measures 2.1:1. Both are under the 4.5:1 WCAG AA threshold. They are 98.css's own values, repainting them would make the specimen wrong, so they stand and are named here instead. An audit of all 216 text nodes on this page finds no other failure, and nothing a reader or a player needs exists only inside a title bar.

Type. public/fonts/MSSansSerif.woff2 is a clean-room FontStruct recreation, not Microsoft's font. Verbatim as its licence requires: The FontStruction "MS Sans Serif" (https://fontstruct.com/fontstructions/show/1384746) by "lou" is licensed under a Creative Commons Attribution Share Alike license (http://creativecommons.org/licenses/by-sa/3.0/). Its 11px on 13px metrics were checked against the FONTINFO block of sserife.fon on the build machine, which is Microsoft's file and is deliberately not in this repo.

Cursors. The pointing hand in round 2 is squiddy22-linkselect.cur by Squiddy22, published on rw-designer.com on 5 May 2007 under Attribution Required (CC BY), shipped unmodified and served with no CSS hotspot coordinates at all. The effective click point is then (0,0), which is both the number written in the file's own header and the top-left fallback, so this page cannot tell you which of the two the browser used and does not claim to. The five-pixel gap to the drawn fingertip is the same either way, and that gap is the round. The other six real files in the strip above are by Squiddy22, Vlasta and chrisyco, same gallery, same licence, each credited and linked. Every other cursor in the game is original artwork generated for this plate by curfmt/make-cur.py and curfmt/make-cur-128.mjs, which write valid .cur bytes. Two of those hotspot numbers are measurements out of real files: round 1's (2,2) is the number vlasta-smooth-arrow.cur declares, and round 3's (16,16) is the Advanced Crosshair number. Two are not measurements of anything: the 128 px cursor's (120,120) and the proof file's (21,25) were picked by us to make the offset large enough to see, and no file in the corpus declares either, because every file in the corpus is 32 by 32. Nothing from cursors-4u.com is used: that site is all rights reserved, verified 2026-08-04.

Recreation versus emulation, stated plainly. Nothing here emulates Windows or a browser of the period. The window chrome reproduces measured values from 98.css. The hotspot failure is not simulated on the mouse path: the offsets are declared in the cursor file's own header or in the CSS rule, and the browser applies them, so the click really does land where the file says rather than where the arrow is drawn. Hit testing is ordinary DOM hit testing with no forgiveness radius and no correction. Two things on this page are ours rather than the browser's, and they are labelled as such: the 128 px band across the top of round 4 recreates a clampdown that browsers really do apply near their own chrome, and the keyboard MouseKeys pointer applies the round's declared offset by hand, because a hotspot cannot lie to a keyboard and the mode would otherwise be a way around the lesson.

Sound. The real Windows 98 sounds, rehosted from a public archive of them: DING, CHORD, TADA, CHIMES. They are Microsoft's, credited here rather than claimed. The one-second tick is still a single oscillator, because Windows never shipped a ticking clock. The period way to make a page click was an invisible EMBED with MASTERSOUND, purely so JavaScript had an object to call .play() on.

Claims deliberately absent. That users or authors complained in writing about wrong hotspots between 1998 and 2005: searched, not found. That Internet Explorer 4 had url() cursors: the 1999-05-08 MSDN snapshot lists keywords only, and url() is marked "Internet Explorer 6 Public Preview and later". What Netscape 4 did with the property. The date Blink or WebKit adopted the 128 px limit, which is attributed to Mozilla only because Chromium's history pages return 403. Any statistic about how many sites used custom cursors: the corpus is 141 files from six authors on one gallery, and it measures a gallery, not the web. That any statistic on this page describes the period: the corpus spans 2006 to 2026, and 79 of its 141 files were uploaded in July and August 2026, so every count quoted above is cut to the 62 files from the four sets published in 2006 and 2007 and says so out loud. The 2026 sets are measured in the reference folder and are not evidence about the old web.