Skip intro forever: the rise, glory and slow death of Flash
From vector cartoons for 28.8k modems to the most exploited plugin on the Internet: SWF, ActionScript, JIT spraying, “Thoughts on Flash” and the kill switch that even stopped trains.
There was a time when opening a pizzeria's website meant forty seconds of loading, watching a logo bounce to techno music and desperately hunting for the SKIP INTRO button. The menu was a spinning circle, the browser's back button did nothing and Google could not see a thing. That was the Flash web, and for about ten years it simply was the web.
In a few months it will be five years since Flash was switched off for good. Here is how it happened: a plugin built to draw cartoons became the most used (and most exploited) platform on the Internet, and then disappeared overnight.
1993–1996: a drawing program that wanted to be something else
It all starts with SmartSketch, a vector drawing program for pen computers written by Jonathan Gay at his small company, FutureWave Software. Pen computers never take off; the Internet does. FutureWave adds animation and a player for the browsers of the day, and in 1996 launches FutureSplash Animator. Early customers include MSN and Disney.
In December 1996 Macromedia buys FutureWave and renames the product Macromedia Flash 1.0. The winning idea is technical. In 1996 modems run at 28.8 kbit/s, and a vector animation weighs a fraction of an animated GIF of the same size and scales to any resolution.
Inside a SWF file
The SWF format is a small masterpiece of compactness, designed for modems. It opens with a three-byte signature: FWS for uncompressed files, CWS when the rest is zlib-compressed (from Flash 6) and ZWS for LZMA (from Flash 11). Then come the version number and the file length. Then the most "1990s" part: a rectangle holding the stage size, packed at the bit level rather than in bytes, and measured in twips, twentieths of a pixel.
import struct, zlib
def swf_header(path):
data = open(path, "rb").read()
sig, ver, length = data[:3], data[3], struct.unpack("<I", data[4:8])[0]
body = zlib.decompress(data[8:]) if sig == b"CWS" else data[8:]
nbits = body[0] >> 3 # 5 bits: how many bits per field
bits = int.from_bytes(body[:(5 + 4 * nbits + 7) // 8], "big")
total = (5 + 4 * nbits + 7) // 8 * 8
field = lambda i: (bits >> (total - 5 - nbits * (i + 1))) & ((1 << nbits) - 1)
xmin, xmax, ymin, ymax = (field(i) for i in range(4))
off = (5 + 4 * nbits + 7) // 8
fps = body[off + 1] + body[off] / 256 # frame rate in 8.8 fixed point
return sig.decode(), ver, length, (xmax - xmin) / 20, (ymax - ymin) / 20, fps
# ('CWS', 9, 48213, 550.0, 400.0, 24.0) -> the classic 550x400 stage at 24 fpsAfter the header, the file is a sequence of tags, each with a code and a length: DefineShape for shapes, PlaceObject2 to put them on stage, ShowFrame to move to the next frame, DoAction for code. Shapes are quadratic Bézier curves, and every edge records which fill is on its left and which is on its right. A player can skip tags it does not understand, which is why a SWF from 1998 still opened in the 2020 player.
2000–2006: ActionScript, or when the cartoon learned to code
Flash was built for animators, but programmers soon took it over. Code arrived in three stages:
- ActionScript 1 (Flash 5, 2000): an ECMAScript dialect run by AVM1, a fairly slow stack-based virtual machine. You could attach code to any frame or button, so a project's logic ended up scattered across hundreds of places in the timeline. Debugging was a treasure hunt.
- ActionScript 2 (2003): classes, types and
extends, but only on the surface. The compiler turned everything into the same AVM1 bytecode. - ActionScript 3 (Flash Player 9, 2006): a brand-new VM, AVM2, with typed bytecode and a JIT compiler. It was up to ten times faster. Adobe donated the engine, Tamarin, to Mozilla, which was meant to use it for ECMAScript 4. ES4 was abandoned in 2008, and AS3 remains the only language in the world that looks like the JavaScript that never was.
Meanwhile, in 2005, Adobe buys Macromedia for $3.4 billion. The same year YouTube launches, using Flash for video: the FLV format, first with the Sorenson Spark codec, then On2 VP6, then H.264 from 2007. Flash is installed on more than 95% of Internet-connected computers, and it is no exaggeration to say that video on the web is Flash.
The golden age (which was also the bad age)
By the mid-2000s Flash is everywhere, and it brings a set of problems with it:
- All-Flash websites. A single 3 MB SWF held the entire site: no URLs for individual pages, no back button, no selectable or indexable text, no accessibility. The percentage preloader was an art form of its own.
- The SKIP INTRO button. Animated intros were so common that skipping them became a universal habit. Plenty of designers hated them before users did.
- Performance. One Flash banner ad could keep a CPU core at 100%. On Macs the fan spun up as soon as you opened a news site.
- Crashes. The plugin ran inside the browser's process, so when Flash crashed the whole browser went down. Firefox introduced
plugin-container, a separate process for plugins, in 2010 largely for this reason. "Shockwave Flash has crashed" became part of popular culture. - Privacy. Local Shared Objects, the "Flash cookies", survived clearing the browser's cookies. Some services used them to bring deleted cookies back to life, the so-called zombie cookies.
At the same time, Flash was the tool a whole generation used to learn animation and game making. Newgrounds, Homestar Runner, the games on Miniclip and Kongregate, FarmVille: an entire creative industry born inside a plugin.
Security: the plugin with more holes than Swiss cheese
The serious problem, though, was security. An NPAPI plugin was native C++ code that took complex binary files from any website, parsed them with hastily written parsers, compiled them with a JIT, and was installed on 95% of PCs. For exploit writers it was the perfect target. Flash piled up more than a thousand CVEs and was for years one of the exploit kits' favourite components.
Two techniques became famous:
- JIT spraying (Dion Blazakis, 2010): specially built ActionScript expressions, such as a long chain of
XORs with carefully chosen constants, make the JIT compiler write machine code into executable memory with the shellcode hidden inside the constants. This bypassed DEP. Vector.<uint>corruption: a small overflow overwrites the length field of an AS3 vector, giving you a vector as long as all of memory, which means arbitrary read and write. In 2015 Adobe, with help from Google Project Zero, added protections such as separate heaps and length checks.
The low point came in July 2015. Hacking Team, an Italian company that sold surveillance software to governments, was breached, and among the 400 GB of leaked files were several Flash 0-day exploits, which ended up in exploit kits within hours. Mozilla blocked Flash in Firefox. Alex Stamos, Facebook's chief security officer, publicly asked Adobe to announce an end-of-life date.
2007–2010: the iPhone and "Thoughts on Flash"
By then an even bigger problem had arrived. In 2007 the iPhone launched without Flash support. For a while it looked like a missing feature. Then it became a choice.
In April 2010 Steve Jobs published "Thoughts on Flash", an open letter with six objections: Flash is proprietary; the "full web" is now done with H.264 and HTML5; Flash is the main cause of crashes on Macs and has security problems; software video decoding drains the battery; Flash content is designed for the mouse, not fingers; and Apple does not want a third-party layer between apps and the platform. Setting aside Apple's commercial interests, he was technically right about almost all of it.
Adobe tried Android instead: Flash Player 10.1 reached phones in 2010. On a single-core ARM processor, though, the experience was what you would expect. In November 2011 Adobe gave up on mobile Flash.
2010–2020: death by a thousand cuts
Flash did not die from a single decision. It was replaced piece by piece by web standards:
| Flash was used for... | Replaced by |
|---|---|
| Video | <video>, H.264/VP9, Media Source Extensions (YouTube defaults to HTML5 in 2015) |
| Graphics and animation | <canvas>, SVG, CSS animations, WebGL |
| Audio | Web Audio API |
| Webcam and microphone | WebRTC, getUserMedia |
| Sockets | WebSocket |
| High-performance games | asm.js, then WebAssembly |
Browsers did the rest. Chrome dropped NPAPI support in 2015 (Flash survived only because Google bundled it as a sandboxed PPAPI plugin), then made Flash click-to-play and finally blocked it by default. Firefox removed every NPAPI plugin except Flash in 2017.
On 25 July 2017 Adobe announced the official date: Flash Player would no longer be supported after 31 December 2020. Apple, Google, Microsoft, Mozilla and Facebook published their own plans to remove it on the same day.
12 January 2021: the time bomb
Adobe did not just stop shipping updates. The final versions of Flash Player contain an expiry date: from 12 January 2021 the player refuses to run any content and shows an icon pointing to the end-of-life page. Microsoft also shipped a Windows update (KB4577586) that removed Flash from the system.
That is when the world found out who was still using Flash, in very concrete ways:
- the railway network in Dalian, China, was partly halted for almost a day because its train management system was written in Flash. The problem was "fixed" by installing an old version of the player, without the expiry date;
- South Africa's tax agency, which used Flash forms for tax returns, rushed out its own browser with Flash built in;
- in China, Flash lives on in a version distributed by a local Adobe partner, which was criticised for years for bundling adware.
Every sysadmin has a similar memory: a switch management page, a virtualisation console or a NAS whose web panel, overnight, showed nothing but a grey puzzle piece.
What is left, as of September 2025
Almost five years later, Flash is dead but its content lives on thanks to a few preservation projects:
- Ruffle: a Flash emulator written in Rust and compiled to WebAssembly, which runs directly in the browser with no plugin. AVM1 support is very good; AS3 support came later but improves with every release. The Internet Archive and Newgrounds use it to bring thousands of animations and games back to life.
- Flashpoint Archive: a volunteer project that has archived more than a hundred thousand web games and animations, with a launcher that makes them playable offline.
- The editor never went away: since 2016 it has been called Adobe Animate and exports to HTML5 Canvas. The AIR runtime passed to Harman, which maintains it for the apps that still use it.
There is an irony here. Ruffle is safe thanks to Rust and the WebAssembly sandbox, exactly the two things Flash lacked: memory safety and an isolated environment.
TL;DR for those who clicked SKIP INTRO
| Year | Event | Comment |
|---|---|---|
| 1996 | FutureSplash → Macromedia Flash | Vector animation for 28.8k modems |
| 2000 | ActionScript 1 / AVM1 | Code glued to frames |
| 2005 | Adobe buys Macromedia; YouTube launches | Web video is Flash |
| 2006 | ActionScript 3 / AVM2 + JIT | Fast, typed, and great for JIT spraying |
| 2007 | iPhone ships without Flash | The beginning of the end |
| 2010 | "Thoughts on Flash" | Six reasons, mostly sound |
| 2015 | Hacking Team leak | The world asks for an end-of-life date |
| 2017 | EOL announced | Date set: 31/12/2020 |
| 12 Jan 2021 | The kill switch | Even some trains in Dalian stop |
| Today | Ruffle, Flashpoint | Flash lives on inside a sandbox |
The engineering moral: a technology can succeed because it solves a real problem (in 1996 the web could do neither animation nor video) and then fail because it becomes a proprietary layer that nobody else can fix. Open standards are slower, but they get there in the end.
See you at the next bit's tale. No need for a skip-intro button this time. 🧩