Est. 2003 Intermediate

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

Paradigm Event-driven, state-based, imperative; with object-interaction features
Typing Static, weak (with automatic numeric and key/string coercions)
First Appeared 2003 (with the public launch of Second Life)
Latest Version No independent version number; continuously updated as part of Second Life (Mono engine since 2008)

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:

TypeDescription
integerA 32-bit signed whole number (−2,147,483,648 to 2,147,483,647).
floatA single-precision decimal number.
stringA sequence of characters in double quotes.
keyA UUID identifying an avatar, object, texture, sound, or other asset.
vectorThree floats in angle brackets, used for positions, colors (RGB), and velocities, e.g. <1.0, 0.0, 0.5>.
rotationA quaternion of four floats (x, y, z, s) representing 3D orientation.
listAn 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

2003
Second Life launches publicly (reportedly June 23, 2003), with the Linden Scripting Language (LSL) provided as the in-world language residents use to script object behavior.
2006
Second Life enters a period of rapid growth and mainstream press attention, dramatically expanding the community of LSL scripters building gadgets, vehicles, and interactive content.
2008
Linden Lab introduces the Mono scripting engine: it reaches the Beta Grid around January 29, 2008, and the main production grid on August 29, 2008, compiling LSL to Mono bytecode and raising the per-script memory limit from 16 KB to 64 KB.
2009
Around this period Linden Lab expands LSL networking with HTTP capabilities, including outbound requests via llHTTPRequest and inbound HTTP-in (the LSL HTTP server) that lets external systems call scripts in-world.
2013
Native JSON manipulation functions (such as llJsonGetValue and llJsonSetValue) are added around this time, making it easier for scripts to exchange structured data with web services.
2015
The Experience tools framework is rolled out around this period, allowing groups of scripts and objects to share permissions and persistent key-value data under a single named Experience.
2020
LSL remains in active use and continues to receive incremental function additions as Linden Lab maintains and extends Second Life well into its second decade.

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.

Language Influence

Influenced By

Running Today

Run examples using the official Docker image:

docker pull
Last updated: