Rumble Comments API

Beta

Returns the public comments of a Rumble video, short or live stream, replies included, a page at a time: text, the commenter's username, name, avatar and badges, posting time, likes and dislikes, reply count, the comment each reply answers, a permalink, and whether the video's own channel wrote it. Sort newest first (the default, which also supports since and until) or in Rumble's Sort by likes order, and follow page.next_cursor for more. Accepts every Rumble video link form, embed links included, or a bare video ID.

Get 100 free creditsAPI referenceTry it

Price
From 1 credit per page$0.75–$1.45 per 1,000 pages
Request
GET /v1/rumble/commentsOne API key, one JSON schema
Input
urle.g. https://rumble.com/v79xhhm-discovery-why-glenn-wants-israel-to-sue-the-new-york-times.html
Page size
Up to 500 comments

Use cases

What teams build with it. From one request.

  • Track audience reactions to Rumble videos and streams
  • Monitor new comments since a date
  • Analyze whole discussion threads, replies included
  • Build datasets of public comments for research

What you get

Comments in one schema. The same on every platform.

platformstring
Platform ID (tiktok, youtube, …).
idstring
Platform-native comment ID (string; Reddit without t1_).
post_idstring
ID of the post commented on (equals post.id).
parent_idstring
ID of the comment this replies to; null for top-level comments.
urlstring
Permalink, when the platform has one.
textstring
Comment body as plain text.
authorobject
The commenting account.
published_atstring
When the comment was posted, RFC 3339 UTC. Where the platform shows only a relative time ("3 weeks ago"), the latest time that label allows (the fetch time minus the stated amount), listed in approximate_fields.

Every field, its type and when it is null: the response reference and the comment schema.

Example request

cURL
curl -G 'https://staging.socialtap.dev/v1/rumble/comments' \
  --data-urlencode 'url=https://rumble.com/shorts/v7h29za' \
  -H "x-api-key: $SOCIALTAP_API_KEY"
Node.js
const params = new URLSearchParams({
  url: "https://rumble.com/shorts/v7h29za",
});
const res = await fetch(`https://staging.socialtap.dev/v1/rumble/comments?${params}`, {
  headers: { "x-api-key": process.env.SOCIALTAP_API_KEY ?? "" },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
const { data, page, meta } = body;
console.log(data, meta.credits_charged);
Python
import os

import requests

res = requests.get(
    "https://staging.socialtap.dev/v1/rumble/comments",
    params={"url": "https://rumble.com/shorts/v7h29za"},
    headers={"x-api-key": os.environ["SOCIALTAP_API_KEY"]},
)
body = res.json()
if not res.ok:
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
data, page, meta = body["data"], body["page"], body["meta"]
print(data, meta["credits_charged"])
Go
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
)

func main() {
	q := url.Values{}
	q.Set("url", "https://rumble.com/shorts/v7h29za")
	req, err := http.NewRequest("GET", "https://staging.socialtap.dev/v1/rumble/comments?"+q.Encode(), nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("x-api-key", os.Getenv("SOCIALTAP_API_KEY"))
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	var body struct {
		Data  json.RawMessage `json:"data"`
		Page  json.RawMessage `json:"page"`
		Meta  map[string]any  `json:"meta"`
		Error *struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"error"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		log.Fatal(err)
	}
	if body.Error != nil {
		log.Fatalf("%s: %s", body.Error.Code, body.Error.Message)
	}
	fmt.Println(string(body.Data), body.Meta["credits_charged"])
}
PHP
<?php

$query = http_build_query([
    'url' => 'https://rumble.com/shorts/v7h29za',
]);
$ch = curl_init('https://staging.socialtap.dev/v1/rumble/comments?' . $query);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('SOCIALTAP_API_KEY')],
]);
$body = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) {
    throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']);
}
print_r($body['data']);
echo $body['meta']['credits_charged'], PHP_EOL;
Ruby
require "json"
require "net/http"

uri = URI("https://staging.socialtap.dev/v1/rumble/comments")
uri.query = URI.encode_www_form('url' => 'https://rumble.com/shorts/v7h29za')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALTAP_API_KEY")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
body = JSON.parse(res.body)
raise "#{body["error"]["code"]}: #{body["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess)
pp body["data"]
puts body["meta"]["credits_charged"]
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=" + encode("https://rumble.com/shorts/v7h29za");
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://staging.socialtap.dev/v1/rumble/comments?" + query))
            .header("x-api-key", System.getenv("SOCIALTAP_API_KEY"))
            .GET()
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        // An error is {"error": {"code", "message", ...}}; success is {data, meta}, meta.credits_charged its price.
        if (response.statusCode() >= 400) throw new RuntimeException(response.body());
        System.out.println(response.body());
    }

    static String encode(String value) {
        return URLEncoder.encode(value, StandardCharsets.UTF_8);
    }
}
.NET
using System.Text.Json;

using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALTAP_API_KEY"));

var query = string.Join("&",
    "url=" + Uri.EscapeDataString("https://rumble.com/shorts/v7h29za"));
var res = await http.GetAsync("https://staging.socialtap.dev/v1/rumble/comments?" + query);
using var body = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
if (!res.IsSuccessStatusCode)
{
    var error = body.RootElement.GetProperty("error");
    throw new Exception($"{error.GetProperty("code")}: {error.GetProperty("message")}");
}
Console.WriteLine(body.RootElement.GetProperty("data"));
Console.WriteLine(body.RootElement.GetProperty("meta").GetProperty("credits_charged"));
Rust
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = reqwest::blocking::Client::new()
        .get("https://staging.socialtap.dev/v1/rumble/comments")
        .query(&[("url", "https://rumble.com/shorts/v7h29za")])
        .header("x-api-key", env::var("SOCIALTAP_API_KEY")?)
        .send()?;
    let ok = res.status().is_success();
    let body: serde_json::Value = res.json()?;
    if !ok {
        return Err(format!("{}: {}", body["error"]["code"], body["error"]["message"]).into());
    }
    println!("{} {}", body["data"], body["meta"]["credits_charged"]);
    Ok(())
}
200 OK
{
  "data": [
    {
      "approximate_fields": [
        "published_at"
      ],
      "author": {
        "avatar_url": "https://hugh.cdn.rumble.cloud/video/z0/e/b/M/g/ebMgr.asF.1-4qu5ac-tnkdxy.jpeg",
        "display_name": "inshallakhan",
        "id": null,
        "is_verified": false,
        "url": "https://rumble.com/user/inshallakhan",
        "username": "user/inshallakhan"
      },
      "edited_at": null,
      "id": "620403472",
      "is_by_post_author": false,
      "is_edited": null,
      "is_liked_by_author": null,
      "is_pinned": null,
      "metrics": {
        "like_count": 0,
        "reply_count": 0
      },
      "parent_id": null,
      "platform": "rumble",
      "platform_specific": {
        "rumble": {
          "author_badges": [],
          "dislike_count": 0
        }
      },
      "post_id": "v7h29za",
      "published_at": "2026-10-23T03:31:00Z",
      "text": "oh 😯😯",
      "unknown_fields": [],
      "url": "https://rumble.com/shorts/v7h29za#comment-620403472"
    },
    {
      "approximate_fields": [
        "published_at"
      ],
      "author": {
        "avatar_url": "https://hugh.cdn.rumble.cloud/video/z0/C/E/l/b/CElbr.asF-4pzq1o-ti0cx0.jpeg",
        "display_name": "CassandraB89",
        "id": null,
        "is_verified": false,
        "url": "https://rumble.com/user/CassandraB89",
        "username": "user/CassandraB89"
      },
      "edited_at": null,
      "id": "620356964",
      "is_by_post_author": false,
      "is_edited": null,
      "is_liked_by_author": null,
      "is_pinned": null,
      "metrics": {
        "like_count": 0,
        "reply_count": 0
      },
      "parent_id": null,
      "platform": "rumble",
      "platform_specific": {
        "rumble": {
          "author_badges": [],
          "dislike_count": 0
        }
      },
      "post_id": "v7h29za",
      "published_at": "2026-10-22T13:01:00Z",
      "text": "🐈👌🏻🧡",
      "unknown_fields": [],
      "url": "https://rumble.com/shorts/v7h29za#comment-620356964"
    },
    {
      "approximate_fields": [
        "published_at"
      ],
      "author": {
        "avatar_url": null,
        "display_name": "SkyeWalker0504",
        "id": null,
        "is_verified": false,
        "url": "https://rumble.com/user/SkyeWalker0504",
        "username": "user/SkyeWalker0504"
      },
      "edited_at": null,
      "id": "620301964",
      "is_by_post_author": false,
      "is_edited": null,
      "is_liked_by_author": null,
      "is_pinned": null,
      "metrics": {
        "like_count": 1,
        "reply_count": 0
      },
      "parent_id": null,
      "platform": "rumble",
      "platform_specific": {
        "rumble": {
          "author_badges": [],
          "dislike_count": 0
        }
      },
      "post_id": "v7h29za",
      "published_at": "2026-10-21T15:29:00Z",
      "text": "Looks like a Minecraft cat.",
      "unknown_fields": [],
      "url": "https://rumble.com/shorts/v7h29za#comment-620301964"
    }
  ],
  "page": {
    "has_more": false,
    "next_cursor": null,
    "next_cursor_expires_at": null,
    "end_reason": "end"
  },
  "meta": {
    "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
    "platform": "rumble",
    "source": "api",
    "is_cached": false,
    "credits_charged": 1,
    "latency_ms": 0,
    "fetched_at": "2026-10-25T12:00:00Z",
    "input": {
      "kind": "video",
      "id": "v7h29za",
      "url": "https://rumble.com/v7h29za"
    },
    "credits_remaining": 9999,
    "client_request_id": null,
    "warnings": [],
    "mode": "live"
  }
}

Long arrays and strings are shortened for display; real responses are complete.

Pricing

Pay per page. Only when it succeeds.

SourcePrice per successful pagePer 1,000 pages
Platform API api1 credit$0.75–$1.45
  • Failed requests are free: errors cost 0 credits.
  • Cache hits are free: responses served from the cache cost 0 credits.
  • Credits never expire.
  • One credit balance for every endpoint and platform.

Credit packs · How this endpoint is priced · How credits work

FAQ

Questions, answered.

How much does the Rumble Comments API cost?
1 credit for platform api results (meta.source = api) per page of up to 500 items, charged for every successful page, empty pages included. SocialTap credits cost $0.75–$1.45 per 1,000 depending on the pack.
How do I get the next page?
Repeat the same request with cursor set to page.next_cursor from the previous response, keeping the other parameters. When page.has_more is false there are no more items. Cursors expire after 24 hours.
Am I charged for failed requests?
No. Requests that return an error cost 0 credits. Responses served from the cache are free too.

Start with 100 free credits. No card required.

Test keys answer every endpoint from recorded responses, free, so you can build before you spend. Failed requests are always free.

Get your API keyRead the API reference