Alife Virtual School - Class 12: HTTP Requests in LSL
HTTP Requests in LSL — Free class in Alife Virtual School
Connecting Your In-World Creations to the World Wide Web
Welcome, future master scripter, to Class 12 at the Alife Virtual School! You’ve learned how to build, texture, and write basic scripts. You’ve made objects that move, talk, and react to avatars. But what if you could make your creations truly live? What if an object in Alife Virtual could know the real-world weather, display live stock prices, or even talk to an advanced AI on the internet?
This is where the magic happens. By learning to use HTTP requests in LSL (Linden Scripting Language), you will unlock the ability to connect your in-world objects to the vast expanse of the World Wide Web. This skill is the gateway to creating some of the most dynamic and impressive content you'll see across the grid, from live scoreboards for sports events to AI-powered chatbots and self-updating vendor systems. You're not just scripting an object anymore; you're building a bridge between the virtual world and the real world.
In Alife Virtual, where you have a free private island with 10,000 prims to build on, this skill is especially powerful. You have the space and the resources to build large-scale, data-driven projects without the crippling land fees you'd find elsewhere. Imagine a whole sim that changes its environment based on the real-world time of day and weather, all powered by the techniques you'll learn today. Let's get started!
What You Will Learn
By the end of this advanced tutorial, you will be able to:
- Understand the core concepts of the HTTP request/response cycle.
- Confidently use the
llHTTPRequest()function to send requests to external web servers. - Process incoming data using the
http_responseevent. - Distinguish between
GETandPOSTrequests and know when to use each. - Parse simple data from an API response to extract the information you need.
- Build a functional, real-world example: a live cryptocurrency price ticker.
- Avoid common pitfalls and troubleshoot your HTTP scripts effectively.
Prerequisites
This is an advanced class. Before you begin, you should be comfortable with the fundamentals of LSL scripting. We recommend you have a solid grasp of:
- Variables, functions, and events.
- States and state changes.
- String and list manipulation.
- Using the LSL editor in the Firestorm Viewer.
If you need a refresher, please feel free to browse our earlier, free classes at the Alife Virtual School. You’ll also need your free full-body mesh avatar and a place to build—which is no problem since every one of our 1,148,000+ members can claim a free 65,536 sqm private island to call their own!
Main Tutorial: Making the Web Work for You
Part 1: The Theory - What is an HTTP Request?
Think of it like ordering food from a restaurant.
- You (the script) decide what you want (e.g., the current price of Bitcoin).
- You write down your order and give it to the waiter. This is the HTTP Request. Your script uses the
llHTTPRequest()function to send this "order" to a specific web address (URL). - The kitchen (the web server/API) prepares your order.
- The waiter brings your food back to your table. This is the HTTP Response. Your script receives this "food" (the data) in a special event called
http_response.
The key is that this is an asynchronous process. Your script doesn't stop and wait for the answer. It sends the request and continues running. When the response arrives (which could be milliseconds or seconds later), the http_response event is triggered, and your script can then process the data.
Part 2: The Core LSL Functions
Two main components make this all work in LSL:
1. The Function: llHTTPRequest(key url, list parameters, string body)
This is the function you call to send your "order".
key url: A unique ID for your request. You'll get this same ID back in the response, so you know which request the response is for. We usually generate a random one withllGenerateKey(). Wait, that's not right. The first parameter is the URL, the request ID is returned by the function. Let me correct this. The official LSL documentation states:key llHTTPRequest(string url, list parameters, string body). The function *returns* a key. I'll write it correctly.
Let's correct that. The function signature is `key llHTTPRequest(string url, list parameters, string body)`.
string url: The web address you are requesting data from. For example, an API endpoint.list parameters: A list of special constants and their values that define the request. The most common are:HTTP_METHOD: The type of request. Usually"GET"(to retrieve data) or"POST"(to send data).HTTP_MIMETYPE: The format of the data you are sending. For example,"application/json".
string body: The data you want to send with your request. This is primarily used forPOSTrequests. ForGETrequests, this is usually an empty string ("").
The function returns a key, which is the unique ID for this specific request. You need to save this key to match it with the incoming response.
2. The Event: http_response(key request_id, integer status, list metadata, string body)
This event is automatically triggered in your script when the web server sends back a response.
key request_id: The unique ID returned by the originalllHTTPRequest()call. This is how you match the response to your request.integer status: The standard HTTP status code.200means "OK" (success!).404means "Not Found".403means "Forbidden". You should always check for200before trying to process the data.list metadata: Information about the response, rarely used in basic scripting.string body: This is the payload! It's the actual data sent back from the server, often as plain text, JSON, or XML.
Part 3: Step-by-Step Example: Building a Live Bitcoin Price Board
Let's build something practical. We'll create a simple prim that shows the current price of Bitcoin in USD and updates when you touch it. We'll do this on your free island, which you can claim right after you register for Alife Virtual. Remember, our platform uses the same Firestorm Viewer as Second Life, so your skills are 100% transferable, but here, your creative freedom isn't limited by upload fees or land costs!
Step 1: Find a Free Public API
An API (Application Programming Interface) is a way for computers to talk to each other. We need an API that provides cryptocurrency prices. A great, simple one is CoinGecko.
The URL we will use is: https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd
If you visit that URL in your web browser, you'll see a simple text response: {"bitcoin":{"usd":68000.50}} (the price will vary, of course). This is the data we want to get into our script.
Step 2: Set Up Your Object in Alife Virtual
- Log into Alife Virtual using the Firestorm Viewer.
- Teleport to your free private island. (If you haven't claimed it, visit this page after registering).
- Right-click the ground and choose Build. A wooden cube will appear. This is your price board.
- Right-click the cube and choose Edit.
- In the edit window, go to the Content tab.
- Click the New Script button. A new script named "New Script" will be created and opened.
[Image: A screenshot showing the in-world editor in Alife Virtual. A prim is selected, and the 'Content' tab is open, highlighting the 'New Script' button.]
Step 3: Write the Script - Making the Request
Delete the default "Hello, Avatar!" code and replace it with the following. We'll start by declaring our variables and setting up the touch event to fire the request.
// --- Global Variables ---
string API_URL = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd";
key g_request_id; // To store the ID of our request
default
{
state_entry()
{
llSetObjectDesc("Bitcoin Price Ticker");
llSetText("Click me to update price...", <1.0, 1.0, 1.0>, 1.0);
}
touch_start(integer total_number)
{
llSetText("Fetching price...", <1.0, 0.8, 0.0>, 1.0);
// Send the HTTP request and store the returned key
g_request_id = llHTTPRequest(API_URL, [], "");
}
}
Tip: We use a global variableg_request_idto hold the key thatllHTTPRequest()gives us. This is crucial for identifying the response when it arrives. Using a prefix like "g_" for global variables is a good coding practice.
Step 4: Handle the Response
Now, let's add the http_response event to our script. This code will "listen" for the reply from the CoinGecko server.
Add this event inside your default state, after the touch_start event.
http_response(key request_id, integer status, list metadata, string body)
{
// First, check if this response is for our request
if (request_id == g_request_id)
{
// Next, check if the request was successful
if (status == 200)
{
// For now, let's just print the body to see what we got
llOwnerSay("Response received: " + body);
// We will parse this data in the next step!
// For now, let's just show a success message.
llSetText("Data received! Processing...", <0.0, 1.0, 0.0>, 1.0);
}
else
{
// The request failed! Tell the user.
llSetText("Error: Failed to fetch price. Status: " + (string)status, <1.0, 0.0, 0.0>, 1.0);
llOwnerSay("HTTP request failed with status code: " + (string)status);
}
}
}
Save your script. Now, touch the object in-world. You should see the text change to "Fetching price..." and then, in your local chat, a message like: Response received: {"bitcoin":{"usd":68000.50}}. This confirms your script is successfully communicating with the web!
Step 5: Parse the Data and Display It
We have the data, but it's trapped in a string: {"bitcoin":{"usd":68000.50}}. This format is called JSON. While LSL doesn't have a built-in JSON parser, we can use simple string functions for this basic structure.
We'll use llParseString2List to break the string apart using the double quote (") as a delimiter.
Replace the `llOwnerSay` and temporary `llSetText` line inside your `if (status == 200)` block with the following parsing logic:
// --- Start Parsing ---
// The response looks like: {"bitcoin":{"usd":PRICE}}
// We will split the string by the " character.
list parsed_data = llParseString2List(body, ["\""], []);
// The price will be the 4th element in the list, but it has a colon.
// e.g., ":68000.50}}"
string price_part = llList2String(parsed_data, 7); // Index 7 should be the price value
// Let's clean it up by removing the trailing characters '}}' and the colon ':'
// Find the position of the colon
integer colon_pos = llSubStringIndex(price_part, ":");
// Get the substring after the colon
string price_raw = llGetSubString(price_part, colon_pos + 1, -1);
// Remove the closing curly braces
integer brace_pos = llSubStringIndex(price_raw, "}");
string final_price = llGetSubString(price_raw, 0, brace_pos - 1);
// Now, display the final price!
llSetText("Bitcoin: $" + final_price, <1.0, 1.0, 1.0>, 1.0);
llOwnerSay("Current Bitcoin Price: $" + final_price);
Save the script. Now when you touch the cube, it will fetch the live price, parse it, and display it as floating text on the object! Congratulations, you've just built your first web-connected LSL object!
A Note on Parsing: This string parsing method is fragile. If the API changes its JSON structure even slightly, it will break. For more complex data, scripters often write their own robust JSON parsing functions, a topic for a future, even more advanced class!
Part 4: Sending Data with a `POST` Request
What if you want to send data, not just get it? For example, submitting a high score to a web leaderboard. This is done with a POST request. The process is very similar, but you need to configure the `parameters` and `body` in your `llHTTPRequest` call.
Here’s a quick example snippet. Imagine you have a web service (a "webhook") that accepts a player's name and score.
string webhookURL = "https://your-api.com/submit_score";
string playerName = "Explorer_123";
integer playerScore = 9500;
// Create the JSON data to send
string jsonBody = "{ \"name\": \"" + playerName + "\", \"score\": " + (string)playerScore + " }";
// Define the parameters for a POST request
list postParams = [
HTTP_METHOD, "POST",
HTTP_MIMETYPE, "application/json"
];
// Send the request!
llHTTPRequest(webhookURL, postParams, jsonBody);
The server at `webhookURL` would receive the JSON data, and you would still get a confirmation back in your `http_response` event, which you should handle just like you did for the `GET` request.
Common Mistakes and How to Avoid Them
- Ignoring the `request_id`: If you have multiple requests active, you MUST use the `request_id` to know which response belongs to which request.
- Not Checking the Status Code: Always wrap your data processing logic in `if (status == 200)`. Trying to parse data from a failed request (like a 404 or 500 error) will cause script errors.
- API Rate Limiting: Calling an API too frequently (e.g., every second) can get you temporarily blocked. Always check the API's documentation for rate limits. Use a `llSetTimerEvent` to make requests at reasonable intervals (e.g., every 5-10 minutes).
- HTTP vs. HTTPS: Most modern APIs require HTTPS. LSL's `llHTTPRequest` supports HTTPS, but the remote server must support a compatible TLS/SSL protocol. If requests mysteriously fail, this can sometimes be the cause.
- Script Permissions: For a script to make HTTP requests, the object's owner must grant permission. The first time the script runs, you'll get a dialog box asking for permission. Make sure you click "Yes".
Advanced Tips and Tricks
- Managing Multiple Requests: If you need to make several different requests at once, store the request keys in a list. In your `http_response` event, find the index of the `request_id` in your list to determine what to do with the `body`.
- Securely Storing API Keys: Never hard-code private API keys directly into your script if you plan to sell or give away the object. A better method is to have the owner input the key via chat command, which the script then saves in the object's description field (`llSetObjectDesc`) for retrieval.
- Using Headers: Some APIs require custom headers for authentication (e.g., `Authorization: Bearer YOUR_API_KEY`). You can add these to the `parameters` list in `llHTTPRequest`, just like `HTTP_METHOD`.
Practice Exercise: Enhance Your Ticker!
Now it's your turn to apply what you've learned. Modify the Bitcoin price ticker script to do the following. This is a perfect project to try on your free island, where you have plenty of room and prims to experiment.
- Add Ethereum: Modify the `API_URL` to also fetch the price of Ethereum. (Hint: The URL should look like `...&ids=bitcoin,ethereum&...`).
- Update the Parser: Your string parser will need to be adjusted to handle the more complex response, which will now include Ethereum's price.
- Automatic Updates: Use `llSetTimerEvent()` in your `state_entry` to make the script automatically update the price every 10 minutes, without needing to be touched.
Frequently Asked Questions (FAQ)
- 1. Why is my
http_responseevent not firing? - This is usually due to one of three things: 1) You haven't granted the script HTTP permissions. Reset the script (Tools > Reset Scripts in the pie menu) and watch for the permission dialog. 2) The URL is malformed or points to a non-existent domain. 3) The remote server is down or is blocking requests from Alife Virtual's servers.
- 2. Can I connect to a database on my own computer at home?
- Yes, but it's tricky. The HTTP request is made from Alife Virtual's servers, not your personal computer. Therefore, your home server must be accessible from the public internet (not just your local network). This usually involves configuring port forwarding on your router and having a static IP address or a dynamic DNS service.
- 3. What are the limits on HTTP requests in Alife Virtual?
- Like all LSL functions, `llHTTPRequest` is subject to governor limits to prevent abuse. A script can have a limited number of active HTTP requests at one time, and there are limits on the total number of requests per object per minute. These limits are generous for normal use but prevent spamming. Always design your scripts to be efficient.
- 4. This string parsing for JSON is hard. Is there a better way?
- For simple key-value pairs, string parsing is manageable. For complex JSON with nested objects and arrays, scripters often use pre-written library functions that act as a more complete parser. While not built into LSL, you can find many examples of these functions on open-source LSL code repositories. This is an excellent next step once you've mastered the basics here.
Summary and Next Steps
Incredible work! You've just learned one of the most powerful skills in the LSL scripter's toolkit. You now understand how to use llHTTPRequest and http_response to make your in-world objects communicate with the outside web. You've sent GET requests, parsed the data, and displayed it in-world, opening up a universe of possibilities for dynamic, interactive content.
Your next step is to practice! Try the exercise, then dream bigger. Could you build a weather station for your island? A board that displays the latest news headlines? A system that sends you a message on Discord when someone visits your land? With HTTP requests, all of this is now within your reach.
Keep an eye on the Alife Virtual School course list for more advanced classes. We're committed to providing free, high-quality education to help you make the most of your virtual life.
Ready to Build Without Limits?
Everything you learned today can be built and tested for free in Alife Virtual. Join our community of over a million residents and start creating today.
When you register, you get immediate access to:
- A FREE 65,536 sqm private island forever, with no monthly fees. (Compare to Second Life's ~$300/month for the same size).
- 10,000 prims to bring your biggest ideas to life.
- FREE uploads for all your meshes, textures, and animations. No L$ fees, ever.
- Full support for the Firestorm Viewer and 100% compatible LSL scripting.
Your new virtual life is waiting. What will you create?
Register for Alife Virtual Now
🎓 Ready to Practice In-World?
Get your FREE island and practice everything you just learned — no credit card, no monthly fees.
Claim Your Free Island Now →No credit card required · Takes 2 minutes · Your island is FREE forever