How to scrape Facebook city events

Get Facebook city events as JSON with one request. It costs 1 credit.

Preview
The API is in early access. Ask for a key; the examples use api.socialscrape.io.

Before you start

  • An API key, sent in the x-api-key header. Keep it on your server.
  • For this endpoint you send url. The Facebook city events page lists every parameter.

Step 1: Send the request

GET /v1/facebook/events. Pick your language; each one reads the key from SOCIALSCRAPE_API_KEY.

curl
curl -G "https://api.socialscrape.io/v1/facebook/events" \
  -H "x-api-key: $SOCIALSCRAPE_API_KEY" \
  --data-urlencode 'url=https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547'
Python
import os
import requests

params = {
    "url": "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547",
}
res = requests.get(
    "https://api.socialscrape.io/v1/facebook/events",
    headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},
    params=params,
    timeout=60,
)
body = res.json()

if body["ok"]:
    print(body["data"])
else:
    print(body["error"]["code"], body["error"]["message"])
JavaScript
const url = new URL("https://api.socialscrape.io/v1/facebook/events");
url.search = new URLSearchParams({
  url: "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547",
}).toString();
const res = await fetch(url, {
  headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY },
});
const body = await res.json();

if (body.ok) {
  console.log(body.data);
} else {
  console.error(body.error.code, body.error.message);
}
TypeScript
const url = new URL("https://api.socialscrape.io/v1/facebook/events");
url.search = new URLSearchParams({
  url: "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547",
}).toString();
const res = await fetch(url, {
  headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },
});
const body = await res.json();

if (body.ok) {
  console.log(body.data);
} else {
  console.error(body.error.code, body.error.message);
}
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	q := url.Values{}
	q.Set("url", "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547")
	req, _ := http.NewRequest("GET", "https://api.socialscrape.io/v1/facebook/events" + "?" + q.Encode(), nil)
	req.Header.Set("x-api-key", os.Getenv("SOCIALSCRAPE_API_KEY"))
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(res.StatusCode, string(body))
}
PHP
<?php
$query = http_build_query([
    'url' => 'https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547',
]);
$ch = curl_init('https://api.socialscrape.io/v1/facebook/events' . "?" . $query);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["x-api-key: " . getenv("SOCIALSCRAPE_API_KEY")],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($body["ok"]) {
    print_r($body["data"]);
} else {
    echo $body["error"]["code"], " ", $body["error"]["message"], "\n";
}
Ruby
require "net/http"
require "json"

uri = URI('https://api.socialscrape.io/v1/facebook/events')
uri.query = URI.encode_www_form('url' => 'https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALSCRAPE_API_KEY")
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
body = JSON.parse(res.body)

if body["ok"]
  puts body["data"]
else
  puts body["error"]["code"], body["error"]["message"]
end
Java
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class Main {
    public static void main(String[] args) throws Exception {
        String query = "url=" + URLEncoder.encode("https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547", StandardCharsets.UTF_8);
        HttpRequest req = HttpRequest.newBuilder()
            .uri(URI.create("https://api.socialscrape.io/v1/facebook/events" + "?" + query))
            .header("x-api-key", System.getenv("SOCIALSCRAPE_API_KEY"))
            .GET()
            .build();
        HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println(res.statusCode() + " " + res.body());
    }
}
C#
using System;
using System.Net.Http;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALSCRAPE_API_KEY"));
var query = string.Join("&", new[] {
    "url=" + Uri.EscapeDataString("https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547"),
});
var res = await client.GetAsync("https://api.socialscrape.io/v1/facebook/events" + "?" + query);
Console.WriteLine((int)res.StatusCode);
Console.WriteLine(await res.Content.ReadAsStringAsync());

Step 2: Read the response

Results are in data.items. Here is what one item gives you, from a recorded sample.

Python
for item in body["data"]["items"]:
    print(item["title"])
    print(item["id"])
JavaScript
for (const item of body.data.items) {
  console.log(item.title);
  console.log(item.id);
}
Fields printed aboveSample
{
  "title": "90s Day Party: St. Petersburg, FL 💿",
  "id": "1009766568177406"
}

A field the platform does not give comes back as null. The full field list is on the endpoint page.

Step 3: Get the next page

Send the same request with the cursor you got back, until has_more is false. Each page costs its own price.

Python
import os
import requests

url = "https://api.socialscrape.io/v1/facebook/events"
headers = {"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]}
params = {"url": "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547"}

items = []
while len(items) < 100:
    body = requests.get(url, headers=headers, params=params, timeout=60).json()
    if not body["ok"]:
        raise RuntimeError(body["error"]["code"])
    items += body["data"]["items"]
    if not body["has_more"]:
        break
    params["cursor"] = body["cursor"]

print(len(items), "items")
JavaScript
const url = new URL("https://api.socialscrape.io/v1/facebook/events");
url.searchParams.set("url", "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547");
const headers = { "x-api-key": process.env.SOCIALSCRAPE_API_KEY };

const items = [];
while (items.length < 100) {
  const body = await (await fetch(url, { headers })).json();
  if (!body.ok) throw new Error(body.error.code);
  items.push(...body.data.items);
  if (!body.has_more) break;
  url.searchParams.set("cursor", body.cursor);
}

console.log(items.length, "items");

Step 4: Handle errors

Check ok, then branch on error.code and error.retryable, never on the message.

Python
body = res.json()
if not body["ok"]:
    err = body["error"]
    if err["retryable"]:
        ...  # wait a moment and send the same request again
    else:
        raise RuntimeError(f'{err["code"]}: {err["message"]}')
JavaScript
const body = await res.json();
if (!body.ok) {
  const { code, message, retryable } = body.error;
  if (retryable) {
    // wait a moment and send the same request again
  } else {
    throw new Error(`${code}: ${message}`);
  }
}
CodeHTTPRetryMeaning
invalid_params400noA parameter is missing, unknown or has the wrong type.
unsupported_url400noThe URL is not one this endpoint accepts (wrong platform or form).
not_found404noThe platform says this profile, post or item does not exist.

Other errors, such as unauthorized or rate_limited, are on the errors page.

With the SDK

The Python and TypeScript clients wrap all of this: typed errors, retries, and cursor paging. They are in preview and not published yet.

Python
from socialscrape import SocialScrape

client = SocialScrape()  # reads SOCIALSCRAPE_API_KEY

for item in client.paginate(client.facebook.events, url="https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547", max_items=100):
    print(item["title"])
TypeScript
import { SocialScrape } from "socialscrape";

const client = new SocialScrape(); // reads SOCIALSCRAPE_API_KEY

for await (const item of client.paginate(client.facebook.events, { url: "https://www.facebook.com/events/explore/saint-petersburg-florida/111326725552547" }, { maxItems: 100 })) {
  console.log(item.title);
}

What it costs

1 credit. A failed request costs nothing. Add max_age_days to reuse a cached result for 0 credits. Results are kept 30 days.

Next

Questions

How do I watch Facebook city events for new items?

Create a monitor on this endpoint and get new items at a webhook, instead of polling. See the monitors reference.

Which language should I use?

Any. It is plain HTTP and JSON, so every language with an HTTP client works. The tabs show the same request nine ways.

Get a key.

Early access keys go to developers and agent builders first.

Get early access