import requests
cookie = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_RestOfCookieGoesHere"
session = requests.Session()
session.cookies[".ROBLOSECURITY"] = cookie
req = session.post(
url="https://auth.roblox.com/"
)
print(req.status_code) # output the status code
print(req.json()["errors"][0]["message"]) # output the error message
X-CSRF-Token
At this point, we’re now authenticated - but there’s one thing missing. If we try to send a POST request, you’ll notice that the request still fails.
Here's an example of some code that won't work due to the X-CSRF-Token:
# Uses the http.rb gem. Run "gem install http" on your terminal to install it
require "http"
require "json"
COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN"
response = HTTP.cookies({
:".ROBLOSECURITY" => COOKIE
}).post("https://auth.roblox.com")
puts response.status # Print the status code
puts JSON.parse(response)["errors"][0]["message"] # Print the error message
const COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
const response = await fetch("https://auth.roblox.com", {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"Content-Length": "0",
},
method: "POST",
});
const body = await response.json();
console.log(response.status);
console.log(body["errors"][0]["message"]);
// npm install node-fetch
import fetch from "node-fetch"
const COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
const response = await fetch("https://auth.roblox.com", {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"Content-Length": "0",
},
method: "POST",
});
const body = await response.json();
console.log(response.status);
console.log(body["errors"][0]["message"]);
/*
Cargo.toml dependencies:
reqwest = { version = "0.11.4" }
tokio = { version = "1.11.0", features = ["macros", "rt-multi-thread"]}
serde_json = { vesion = "1.0.67"}
*/
use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::Client;
use serde_json::{from_str, Value};
const COOKIE: &str = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
#[tokio::main]
async fn main() {
let client = Client::new();
let mut headers = HeaderMap::new();
headers.insert(
"Cookie",
HeaderValue::from_str(&format!(".ROBLOSECURITY={};", COOKIE)).unwrap(),
);
headers.insert("Content-Length", HeaderValue::from_str("0").unwrap());
let response = client
.post("https://auth.roblox.com")
.headers(headers)
.send()
.await
.unwrap();
let status = response.status(); // that feel when .text() consumes the response
let body: Value = from_str(&response.text().await.unwrap()).unwrap();
println!("{}", status);
println!("{}", body["errors"][0]["message"]);
}
local HttpService = game:GetService("HttpService")
-- when inputting your cookie, remove the _| |_ part
local COOKIE = ""
local headers = {
Cookie = string.format(".ROBLOSECURITY=%s", COOKIE)
}
local request = HttpService:RequestAsync({
Method = "POST",
Url = "https://rprxy.deta.dev/auth", -- public proxy that should not be used in production
Headers = headers
})
print(request.StatusCode)
print(HttpService:JSONDecode(request.Body).errors[1].message)
// Uses the Netwonsoft.Json package. Run "dotnet add package Newtonsoft.Json --version 13.0.1" on your terminal to install it.
using System.Net;
using Newtonsoft.Json;
const string roblosecurity = "cookie";
CookieContainer cookies = new CookieContainer();
cookies.Add(new Cookie(".ROBLOSECURITY", roblosecurity, "/", "roblox.com"));
HttpClient httpClient = new HttpClient(new HttpClientHandler()
{
CookieContainer = cookies
});
HttpResponseMessage response = await httpClient.PostAsync("https://auth.roblox.com", null);
dynamic body = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()) ?? throw new Exception("Unable to deserialize body");
Console.WriteLine(response.StatusCode);
Console.WriteLine(body["errors"][0]["message"]);
# Run with "iex -S mix", "RobloxAPI.main()"
# Dependencies:
# [
# {:httpoison, "~> 1.8.0"},
# {:poison, "~> 5.0.0"}
# ]
defmodule RobloxAPI do
@roblosecurity "cookie"
def main() do
headers = %{Cookie: ".ROBLOSECURITY=#{@roblosecurity};"}
case HTTPoison.post("https://auth.roblox.com", "", headers) do
{:ok, response} ->
case Poison.decode(response.body) do
{:ok, body} ->
IO.puts(response.status_code)
List.first(body["errors"])["message"] |> IO.puts()
{:error, error} ->
IO.inspect(error)
end
{:error, error} ->
IO.inspect(error)
end
end
This code should output something like the following:
403 Token Validation Failed
The 403 Forbidden
status code is returned when the client "is not permitted access to the resource despite providing authentication such as insufficient permissions of the authenticated account".
If you saw this while trying to write your own code to access the API, you might ask "why is this error coming up? My .ROBLOSECURITY token is correct, and it worked when I used the "Try it out!" button on the documentation page."
The truth is that this error message isn’t referring to "token" as in your .ROBLOSECURITY token - it’s actually referring to a header that you have to supply to all requests that change data called the X-CSRF-Token
.
To handle this token, each time we send a request, we'll save the X-CSRF-Token
- which is present in the response headers - to a value. Then, if the request failed with a status code of 403, we'll send the request again with the X-CSRF-Token
we just got the first request as a request header.
# With the Session object, we can just store the token in the headers dictionary, but you can pass them directly to each request as well.
import requests
cookie = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_Token"
session = requests.Session()
session.cookies[".ROBLOSECURITY"] = cookie
# send first request
req = session.post(
url="https://auth.roblox.com/"
)
if "X-CSRF-Token" in req.headers: # check if token is in response headers
session.headers["X-CSRF-Token"] = req.headers["X-CSRF-Token"] # store the response header in the session
# send second request
req2 = session.post(
url="https://auth.roblox.com/"
)
print("First:", req.status_code)
print("Second:", req2.status_code)
# Uses the http.rb gem. Run "gem install http" on your terminal to install it
require "http"
require "json"
COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN"
client = HTTP.cookies({
:".ROBLOSECURITY" => COOKIE
})
first_response = client.post("https://auth.roblox.com")
client = client.headers({
:"x-csrf-token" => first_response.headers["x-csrf-token"]
})
second_response = client.post("https://auth.roblox.com")
puts "First: #{first_response.status}"
puts "Second: #{second_response.status}"
const COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
const firstResponse = await fetch("https://auth.roblox.com", {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"Content-Length": "0",
},
method: "POST",
});
const secondResponse = await fetch("https://auth.roblox.com", {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"x-csrf-token": firstResponse.headers.get("x-csrf-token")!,
"Content-Length": "0",
},
method: "POST",
});
console.log(`First: ${firstResponse.status}`);
console.log(`Second: ${secondResponse.status}`);
// npm install node-fetch
import fetch from "node-fetch"
const COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
const firstResponse = await fetch("https://auth.roblox.com", {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"Content-Length": "0",
},
method: "POST",
});
const secondResponse = await fetch("https://auth.roblox.com", {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"x-csrf-token": firstResponse.headers.get("x-csrf-token"),
"Content-Length": "0",
},
method: "POST",
});
console.log(`First: ${firstResponse.status}`);
console.log(`Second: ${secondResponse.status}`);
/*
Cargo.toml dependencies:
reqwest = { version = "0.11.4" }
tokio = { version = "1.11.0", features = ["macros", "rt-multi-thread"]}
*/
use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::Client;
const COOKIE: &str = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
#[tokio::main]
async fn main() {
let client = Client::new();
let mut headers = HeaderMap::new();
headers.insert(
"Cookie",
HeaderValue::from_str(&format!(".ROBLOSECURITY={};", COOKIE)).unwrap(),
);
headers.insert("Content-Length", HeaderValue::from_str("0").unwrap());
let first_response = client
.post("https://auth.roblox.com")
.headers(headers)
.send()
.await
.unwrap();
let mut headers = HeaderMap::new();
headers.insert(
"Cookie",
HeaderValue::from_str(&format!(".ROBLOSECURITY={};", COOKIE)).unwrap(),
);
headers.insert("Content-Length", HeaderValue::from_str("0").unwrap());
headers.insert(
"x-csrf-token",
HeaderValue::from_str(
first_response
.headers()
.get("x-csrf-token")
.unwrap()
.to_str()
.unwrap(),
)
.unwrap(),
);
let second_response = client
.post("https://auth.roblox.com")
.headers(headers)
.send()
.await
.unwrap();
println!("First: {}", first_response.status());
println!("Second: {}", second_response.status());
}
--!strict
local HttpService = game:GetService("HttpService")
-- when inputting your cookie, remove the _| |_ part
local COOKIE = ""
local headers = {
Cookie = string.format(".ROBLOSECURITY=%s", COOKIE)
}
local response1 = HttpService:RequestAsync({
Method = "POST",
Url = "https://rprxy.deta.dev/auth", -- public proxy that should not be used in production
Headers = headers
})
headers["x-csrf-token"] = response1.Headers["x-csrf-token"]
local response2 = HttpService:RequestAsync({
Method = "POST",
Url = "https://rprxy.deta.dev/auth", -- public proxy that should not be used in production
Headers = headers
})
print("First: " .. response1.StatusCode)
print("Second: " .. response2.StatusCode)
using System.Net;
const string roblosecurity = "cookie";
CookieContainer cookies = new CookieContainer();
cookies.Add(new Cookie(".ROBLOSECURITY", roblosecurity, "/", "roblox.com"));
HttpClient httpClient = new HttpClient(new HttpClientHandler()
{
CookieContainer = cookies
});
HttpResponseMessage firstResponse = await httpClient.PostAsync("https://auth.roblox.com", null);
httpClient.DefaultRequestHeaders.Add("x-csrf-token", firstResponse.Headers.GetValues("x-csrf-token").First());
HttpResponseMessage secondResponse = await httpClient.PostAsync("https://auth.roblox.com", null);
Console.WriteLine($"First: {firstResponse.StatusCode}");
Console.WriteLine($"Second: {secondResponse.StatusCode}");
# Run with "iex -S mix", "RobloxAPI.main()"
# Dependencies:
# [
# {:httpoison, "~> 1.8.0"},
# ]
defmodule RobloxAPI do
@roblosecurity "cookie"
def main() do
headers = %{Cookie: ".ROBLOSECURITY=#{@roblosecurity};"}
case HTTPoison.post("https://auth.roblox.com", "", headers) do
{:ok, first_response} ->
headers =
Map.put(
headers,
"x-csrf-token",
# response.headers is a list of tuples, where the first element is the header name and the second the header's value
Enum.find_value(first_response.headers, fn {name, value} ->
if name == "x-csrf-token", do: value
end)
)
case HTTPoison.post("https://auth.roblox.com", "", headers) do
{:ok, second_response} ->
IO.puts("First: #{first_response.status_code}")
IO.puts("Second: #{second_response.status_code}")
{:error, error} ->
IO.inspect(error)
end
{:error, error} ->
IO.inspect(error)
end
end
end
This program will send one request, check if the X-CSRF-Token
was present in the response, and if so will store it back into the session's headers. We then repeat the first request again, and then outputs the status codes from both requests.
This code should output something like the following:
First: 403 Second: 200
This solution works - but it doesn't scale well. If we want to properly do this, we’ll put all of this logic in a function that handles our requests for us and then call that when sending requests. This is (essentially) what the request wrappers in Roblox API wrapper libraries do.
Request function[edit | edit source]
Here's an example of a function that does what we need:
import requests
cookie = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN"
session = requests.Session()
session.cookies[".ROBLOSECURITY"] = cookie
def rbx_request(method, url, **kwargs):
request = session.request(method, url, **kwargs)
method = method.lower()
if method in ["post", "put", "patch", "delete"]:
if "X-CSRF-TOKEN" in request.headers:
session.headers["X-CSRF-TOKEN"] = request.headers["X-CSRF-TOKEN"]
if request.status_code == 403: # Request failed, send it again
request = session.request(method, url, **kwargs)
return request
req = rbx_request("POST", "https://auth.roblox.com/")
print(req.status_code)
# Uses the http.rb gem. Run "gem install http" on your terminal to install it
require "http"
require "json"
COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN"
module HTTPClient
@client = HTTP.cookies({
:".ROBLOSECURITY" => COOKIE
})
def self.rbx_request(verb, url, *args)
response = @client.request(verb, url, *args)
return response if response.status == 200
if response.status == 403
if response.headers.include?("x-csrf-token")
@client = @client.headers({
:"x-csrf-token" => response.headers["x-csrf-token"]
})
return rbx_request(verb, url, args, kwargs)
end
end
response
end
end
response = HTTPClient.rbx_request(:post, "https://auth.roblox.com")
puts response.status
const COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
let xCsrfToken = "";
const rbxRequest = async (
verb: string,
url: string,
body?: string
): Promise<Response> => {
const response = await fetch(url, {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"x-csrf-token": xCsrfToken,
"Content-Length": body?.length.toString() || "0",
},
method: verb,
body: body || "",
});
if (response.status == 403) {
if (response.headers.has("x-csrf-token")) {
xCsrfToken = response.headers.get("x-csrf-token")!;
return rbxRequest(verb, url, body);
}
}
return response;
};
const response = await rbxRequest("POST", "https://auth.roblox.com");
console.log(response.status);
// npm install node-fetch
import fetch from "node-fetch"
const COOKIE = "_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|_TOKEN";
let xCsrfToken = "";
const rbxRequest = async (verb, url, body) => {
const response = await fetch(url, {
headers: {
Cookie: `.ROBLOSECURITY=${COOKIE};`,
"x-csrf-token": xCsrfToken,
"Content-Length": body?.length.toString() || "0",
},
method: "POST",
body: body || "",
});
if (response.status == 403) {
if (response.headers.has("x-csrf-token")) {
xCsrfToken = response.headers.get("x-csrf-token");
return rbxRequest(verb, url, body);
}
}
return response;
};
const response = await rbxRequest("POST", "https://auth.roblox.com");
console.log(response.status);
--!strict
type Table = {[any]: any}
local HttpService = game:GetService("HttpService")
-- when inputting your cookie, remove the _| |_ part
local COOKIE = ""
local headers = {
Cookie = string.format(".ROBLOSECURITY=%s", COOKIE)
}
local function rbxRequest(method: string, url: string, body: Table?)
method = string.upper(method)
local response = HttpService:RequestAsync({
Method = method,
Url = url,
Body = body,
Headers = headers
})
local statusCode = response.StatusCode
if statusCode == 401 then
error("A valid .ROBLOSECURITY cookie is required")
elseif statusCode == 403 then
local responseHeaders = response.Headers
if responseHeaders["x-csrf-token"] then
headers["x-csrf-token"] = responseHeaders["x-csrf-token"]
return rbxRequest(method, url, body)
end
end
return response
end
local response = rbxRequest("POST", "https://auth.roblox.com")
print(response.StatusCode)
// Uses the Netwonsoft.Json package. Run "dotnet add package Newtonsoft.Json --version 13.0.1" on your terminal to install it.
using System.Net;
using System.Text;
using Newtonsoft.Json;
const string roblosecurity = "cookie";
CookieContainer cookies = new CookieContainer();
cookies.Add(new Cookie(".ROBLOSECURITY", roblosecurity, "/", "roblox.com"));
HttpClient httpClient = new HttpClient(new HttpClientHandler()
{
CookieContainer = cookies
});
async Task<HttpResponseMessage> Request(HttpMethod method, Uri url, dynamic? body = null)
{
HttpResponseMessage response = await httpClient.SendAsync(
new HttpRequestMessage(method, url)
{ Content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json") }
);
switch (response.StatusCode)
{
case HttpStatusCode.Unauthorized:
throw new Exception("A valid .ROBLOSECURITY cookie is required");
case HttpStatusCode.Forbidden:
httpClient.DefaultRequestHeaders.Add("x-csrf-token", response.Headers.GetValues("x-csrf-token").First());
return await Request(method, url, body);
}
return response;
}
HttpResponseMessage response = await Request(HttpMethod.Post, new Uri("https://auth.roblox.com"));
Console.WriteLine(response.StatusCode);
# Run with "iex -S mix", "RobloxAPI.main()"
# Dependencies:
# [
# {:httpoison, "~> 1.8.0"},
# {:poison, "~> 5.0.0"}
# ]
defmodule RobloxAPI do
@roblosecurity "cookie"
defp request(verb, url, headers, body \\ %{}) do
case Poison.encode(body) do
{:ok, encoded_body} ->
case HTTPoison.request(verb, url, encoded_body, headers) do
{:ok, response} ->
case response.status_code do
200 ->
{:ok, response}
401 ->
{:error, "Authentication is required for this action"}
403 ->
xcsrf_token =
Enum.find_value(response.headers, fn {name, value} ->
if name == "x-csrf-token", do: value
end)
headers = Map.merge(headers, %{"x-csrf-token": xcsrf_token})
request(verb, url, headers, body)
_ ->
{:error, response}
end
{:error, error} ->
{:error, error}
end
{:error, error} ->
{:error, error}
end
end
def main() do
headers = %{Cookie: ".ROBLOSECURITY=#{@roblosecurity}"}
case request(:post, "https://auth.roblox.com", headers) do
{:ok, response} ->
IO.puts(response.status_code)
{:error, %HTTPoison.Response{status_code: status_code}} ->
IO.puts("Unhandled status code: #{status_code}")
{:error, error} ->
IO.inspect(error)
end
end
end
This code should output something like the following:
200Now that we’ve done this, it makes it marginally easier to send requests to the API.