Linden Scripting Language
The C-inspired, state- and event-driven scripting language that brings interactive objects to life inside the Second Life virtual world.
Created by Linden Lab
Overview
Linden Scripting Language (universally abbreviated LSL) is the programming language residents use to add behavior to objects inside Second Life, the long-running virtual world operated by Linden Lab. Where most languages are run by a compiler or interpreter on your own machine, LSL runs inside the simulation: a script is dropped into the contents of an in-world object (a “prim”), and the object then reacts to the world around it — to being touched, collided with, spoken to on a chat channel, or contacted over HTTP.
LSL gives Second Life much of its character. The vehicles, doors, vendors, games, particle effects, animation systems, and heads-up displays that fill the world are nearly all powered by it. Its syntax is inspired by C, but its structure is fundamentally state- and event-driven, which makes it feel as much like programming a microcontroller or a reactive UI as like writing a conventional program.
History and Origins
LSL appeared together with the public launch of Second Life in 2003 (reportedly on June 23). Linden Lab — the San Francisco company founded by Philip Rosedale — built Second Life as a user-created virtual world, and a scripting language was essential to that vision: rather than ship a fixed catalog of behaviors, the platform let residents program their own. Cory Ondrejka, an early Linden Lab technologist, is frequently credited with leading the design and implementation of the scripting system, though LSL is best attributed to Linden Lab as an organization.
The original language ran on a custom in-house virtual machine. Each script was compiled to a compact bytecode and executed by the simulator (“sim”) that hosts a region of the world. Because thousands of scripts can run simultaneously in a single region, the early VM imposed tight constraints — most famously a fixed 16 KB of memory per script, allocated whether the script needed it or not.
The Mono Era
The most significant change in LSL’s history was the 2008 introduction of the Mono scripting engine. Mono is an open-source implementation of the Common Language Infrastructure (the runtime behind .NET), and Linden Lab adopted it as a faster execution backend. The Mono compiler turns ordinary LSL source into Mono bytecode, which the simulator then runs.
The rollout was staged: Mono reached the Beta Grid around January 29, 2008, and the main production grid on August 29, 2008. Two practical benefits stood out:
- Memory. The per-script ceiling rose from 16 KB to 64 KB, and just as importantly, Mono allocates only the memory a script actually uses instead of reserving the full block up front, as the legacy engine did. Identical scripts can also share compiled bytecode, lowering total region memory in many cases.
- Speed. Linden Lab reported that, for math-intensive benchmark scripts — workloads such as recursion, Mandelbrot-set generation, partial sums, and the NSieve algorithm — Mono ran up to roughly 220 times faster than the legacy LSL engine. This figure is a best case for compute-heavy code; ordinary event-handling scripts that spend most of their time waiting see far more modest gains. The headline number should always be read in that benchmark context rather than as a general “220x faster” claim.
Mono also opened the door, in principle, to other languages compiling to the same bytecode, though LSL has remained the language residents actually write.
Design Philosophy
LSL is shaped by the unusual environment it runs in — a shared, persistent, massively concurrent simulation:
- Everything is an event. A script does not run top-to-bottom and exit; it sits dormant until the world raises an event, then runs a small handler and goes back to sleep. This keeps thousands of scripts cheap to host.
- States as first-class structure. A script is organized into named states, each containing its own set of event handlers. Switching states (with
state somename;) changes which behaviors are active — a natural fit for objects like doors (open vs. closed) or vending machines (idle vs. dispensing). - Safety through sandboxing. Scripts cannot touch the host filesystem or run arbitrary native code. They interact with the world only through a large library of built-in
ll-prefixed functions (named for Linden Lab), which keeps untrusted, user-written code from harming the simulator or other residents. - Approachable but real. The C-like surface syntax was chosen to feel familiar to newcomers, while still being a genuine programming language with variables, functions, and control flow.
Key Features
States and events
Every LSL script must define a default state, and execution begins there. Events are written as specially named handlers inside a state:
default
{
state_entry()
{
llSay(0, "Touch me!");
}
touch_start(integer total_number)
{
llSay(0, "Thanks for the touch!");
}
}
Common events include state_entry (entering a state), touch_start (an avatar clicks the object), listen (chat heard on a channel), collision_start, timer, and http_response. Handlers receive parameters describing the event — for example, touch_start is passed the number of simultaneous touches.
Data types
LSL provides seven built-in types:
| Type | Description |
|---|---|
integer | A 32-bit signed whole number (−2,147,483,648 to 2,147,483,647). |
float | A single-precision decimal number. |
string | A sequence of characters in double quotes. |
key | A UUID identifying an avatar, object, texture, sound, or other asset. |
vector | Three floats in angle brackets, used for positions, colors (RGB), and velocities, e.g. <1.0, 0.0, 0.5>. |
rotation | A quaternion of four floats (x, y, z, s) representing 3D orientation. |
list | An ordered, heterogeneous collection of the other types; lists cannot be nested inside lists. |
The vector and rotation types reflect LSL’s purpose: scripting objects that move and turn in a 3D space, where quaternion math is a daily reality.
The ll function library
Almost everything a script does to the world happens through built-in functions: llSay and llOwnerSay for chat, llSetPos/llSetRot for movement, llListen for hearing chat, llHTTPRequest for web calls, llGiveInventory for handing out items, and hundreds more. Because all world interaction is mediated by these functions, the library effectively is the platform API.
Evolution
After the Mono transition, LSL continued to grow primarily by gaining new functions and capabilities rather than by changing its core syntax. Networking was expanded with HTTP: outbound requests via llHTTPRequest and inbound HTTP-in (the LSL HTTP server), letting in-world scripts talk to and be driven by external web services. Native JSON functions (around 2013) simplified exchanging structured data, and the Experience tools framework (around 2015) let a collection of scripts share permissions and persistent key-value storage under one named Experience. These dates reflect the general period of each feature; LSL’s incremental, server-driven release model means it has no conventional version numbers.
Current Relevance
LSL remains the native language of Second Life more than two decades after launch, and Second Life itself continues to operate and receive updates from Linden Lab. For the platform’s creators, LSL is simply the way things are made: a designer who wants a HUD, a scripted outfit, a game, or an interactive venue writes LSL. That keeps a steady community of scripters, tutorials, open-source snippet libraries, and marketplace products alive around the language, even as it sees little use outside its home world.
It is worth noting that LSL is, by design, tightly coupled to Second Life — it is not a general-purpose language you install and run on your own computer, which is why no standalone Docker image or local toolchain is listed here. (The OpenSimulator project, a separate open-source virtual-world server, implements a compatible scripting dialect, but that is its own ecosystem.)
Why It Matters
Linden Scripting Language is a fascinating case study in language design driven entirely by environment. Its event-and-state structure, its sandboxed ll function library, its quaternion-aware type system, and even its early 16 KB memory ceiling all flow directly from the demands of running untrusted, user-written code inside a shared, real-time, 3D simulation. LSL helped make Second Life one of the first mainstream platforms where ordinary users programmed a persistent virtual world rather than merely inhabiting it — an idea that resonates through later user-scripted worlds and the broader conversation about the “metaverse.” As a domain-specific language, it endures as one of the most widely used and longest-lived scripting languages ever built for a virtual world.
Timeline
Notable Uses & Legacy
Second Life content creators
Independent residents script furniture, vehicles, weapons, games, and interactive gadgets that they sell on the in-world and web-based marketplaces, forming a long-running virtual economy.
Virtual fashion and avatars
Designers use LSL to drive animation overrides (AOs), resizer and texture-change menus, and HUDs (heads-up displays) that let wearers customize clothing, accessories, and avatar bodies.
Education and training simulations
Universities and institutions have built interactive classrooms, role-play scenarios, and visualization exhibits in Second Life, using LSL to make objects respond to learners.
Roleplay and gaming regions
Combat systems, meters, and quest mechanics across roleplay communities are implemented in LSL, with scripts handling damage, inventory, and region-wide messaging.
Live events and interactive art
Builders create reactive installations, particle shows, and venue automation - lighting, seating, and tip jars - that respond to avatars through LSL events.