POST
/api/public/v1/scrape/youtube/channel#
Channel details — name, handle, subscriber and video counts.
Returns profile_api
Parameters
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/channel \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "handle" : "NASA" }} '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/channel" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "handle" : "NASA" }},
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/channel" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { handle: "NASA" } }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/channel" ),
{ parameters: { handle: "NASA" } }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/channel" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "handle" => "NASA" ]]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "handle" : "NASA" },
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/channel" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "channel" ,
"target" : "NASA" ,
"url" : "https://www.youtube.com/@NASA" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/channels#
Channels this channel features or subscribes to publicly.
Returns user_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/channels \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "handle" : "NASA" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/channels" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "handle" : "NASA" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/channels" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { handle: "NASA" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/channels" ),
{ parameters: { handle: "NASA" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/channels" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "handle" => "NASA" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "handle" : "NASA" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/channels" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "channels" ,
"target" : "NASA" ,
"url" : "https://www.youtube.com/@NASA/channels" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/videos#
A channel's uploads, newest first. Use `limit` to say how many.
Returns post_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/videos \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "handle" : "NASA" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/videos" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "handle" : "NASA" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/videos" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { handle: "NASA" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/videos" ),
{ parameters: { handle: "NASA" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/videos" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "handle" => "NASA" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "handle" : "NASA" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/videos" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "videos" ,
"target" : "NASA" ,
"url" : "https://www.youtube.com/@NASA/videos" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/shorts#
A channel's Shorts. Use `limit` to say how many you want.
Returns reel_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/shorts \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "handle" : "NASA" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/shorts" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "handle" : "NASA" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/shorts" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { handle: "NASA" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/shorts" ),
{ parameters: { handle: "NASA" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/shorts" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "handle" => "NASA" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "handle" : "NASA" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/shorts" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "shorts" ,
"target" : "NASA" ,
"url" : "https://www.youtube.com/@NASA/shorts" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/live#
A channel's live streams, past and present. Use `limit` for how many.
Returns post_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/live \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "handle" : "NASA" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/live" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "handle" : "NASA" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/live" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { handle: "NASA" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/live" ),
{ parameters: { handle: "NASA" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/live" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "handle" => "NASA" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "handle" : "NASA" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/live" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "live" ,
"target" : "NASA" ,
"url" : "https://www.youtube.com/@NASA/streams" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/playlists#
A channel's playlists — title, video count and owner.
Returns playlist_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/playlists \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "handle" : "NASA" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/playlists" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "handle" : "NASA" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/playlists" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { handle: "NASA" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/playlists" ),
{ parameters: { handle: "NASA" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/playlists" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "handle" => "NASA" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "handle" : "NASA" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/playlists" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "playlists" ,
"target" : "NASA" ,
"url" : "https://www.youtube.com/@NASA/playlists" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/playlist#
The videos inside one playlist. Use `limit` to say how many.
Returns post_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/playlist \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "playlist_id" : "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/playlist" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "playlist_id" : "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/playlist" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { playlist_id: "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/playlist" ),
{ parameters: { playlist_id: "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/playlist" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "playlist_id" => "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "playlist_id" : "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/playlist" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "playlist" ,
"target" : "PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" ,
"url" : "https://www.youtube.com/playlist?list=PL2aBZuCeDwlRaF6AIey7ulmW1X0SHI1mQ" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/video#
One video's full record — description, counts, keywords, channel.
Returns post_detail_api
Parameters
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/video \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "video_id" : "dQw4w9WgXcQ" }} '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/video" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "video_id" : "dQw4w9WgXcQ" }},
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/video" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { video_id: "dQw4w9WgXcQ" } }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/video" ),
{ parameters: { video_id: "dQw4w9WgXcQ" } }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/video" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "video_id" => "dQw4w9WgXcQ" ]]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "video_id" : "dQw4w9WgXcQ" },
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/video" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "video" ,
"target" : "dQw4w9WgXcQ" ,
"url" : "https://www.youtube.com/watch?v=dQw4w9WgXcQ" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/replies#
Comment replies on a video. Use `limit` to say how many you want.
Returns comment_reply_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/replies \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "video_id" : "dQw4w9WgXcQ" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/replies" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "video_id" : "dQw4w9WgXcQ" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/replies" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { video_id: "dQw4w9WgXcQ" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/replies" ),
{ parameters: { video_id: "dQw4w9WgXcQ" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/replies" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "video_id" => "dQw4w9WgXcQ" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "video_id" : "dQw4w9WgXcQ" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/replies" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "replies" ,
"target" : "dQw4w9WgXcQ" ,
"url" : "https://www.youtube.com/watch?v=dQw4w9WgXcQ" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/hashtag#
Videos under a hashtag. Use `limit` to say how many you want.
Returns post_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/hashtag \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "tag" : "spacex" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/hashtag" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "tag" : "spacex" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/hashtag" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { tag: "spacex" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/hashtag" ),
{ parameters: { tag: "spacex" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/hashtag" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "tag" => "spacex" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "tag" : "spacex" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/hashtag" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "hashtag" ,
"target" : "spacex" ,
"url" : "https://www.youtube.com/hashtag/spacex" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.
POST
/api/public/v1/scrape/youtube/search#
Keyword search. Use `limit` to say how many results you want.
Returns post_feed_api
Parameters
Takes limit — how many results you want. The run is sized from it, and you are billed for exactly that many.
Request
cURL
Python
Node
Ruby
PHP
Go
Copy
curl -X POST https://socialholmes.com/api/public/v1/scrape/youtube/search \
-H "Authorization: Bearer $SOCIALHOLMES_KEY" \
-H "Content-Type: application/json" \
-d ' { "parameters" : { "query" : "mars rover" }, "limit" : 25 } '
import os
import requests
run = requests. post (
"https://socialholmes.com/api/public/v1/scrape/youtube/search" ,
headers={ "Authorization" : f"Bearer {os.environ['SOCIALHOLMES_KEY']}" },
json={ "parameters" : { "query" : "mars rover" }, "limit" : 25 },
). json ()
print ( run[ "id" ], run[ "status" ])
const response = await fetch ( "https://socialholmes.com/api/public/v1/scrape/youtube/search" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${process.env.SOCIALHOLMES_KEY}` ,
"Content-Type" : "application/json" ,
},
body: JSON . stringify ({ parameters: { query: "mars rover" }, limit: 25 }),
})
const run = await response. json ()
console. log ( run. id, run. status)
require "net/http"
require "json"
response = Net:: HTTP . post (
URI ( "https://socialholmes.com/api/public/v1/scrape/youtube/search" ),
{ parameters: { query: "mars rover" }, limit: 25 }. to_json,
"Authorization" => "Bearer #{ENV.fetch('SOCIALHOLMES_KEY')}" ,
"Content-Type" => "application/json"
)
run = JSON . parse ( response. body)
puts run[ "id" ], run[ "status" ]
<?php
$ch = curl_init ( "https://socialholmes.com/api/public/v1/scrape/youtube/search" );
curl_setopt_array ( $ch, [
CURLOPT_POST => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv ( "SOCIALHOLMES_KEY" ),
"Content-Type: application/json" ,
],
CURLOPT_POSTFIELDS => json_encode ([ "parameters" => [ "query" => "mars rover" ], "limit" => 25 ]),
]);
$run = json_decode ( curl_exec ( $ch), true );
echo $run[ "id" ], " " , $run[ "status" ];
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main () {
body, _ := json. Marshal ( map [ string ] any {
"parameters" : map [ string ] string { "query" : "mars rover" },
"limit" : 25 ,
})
req, _ := http. NewRequest ( "POST" , "https://socialholmes.com/api/public/v1/scrape/youtube/search" , bytes. NewReader ( body))
req. Header. Set ( "Authorization" , "Bearer " + os. Getenv ( "SOCIALHOLMES_KEY" ))
req. Header. Set ( "Content-Type" , "application/json" )
res, _ := http. DefaultClient. Do ( req)
defer res. Body. Close ()
var run map [ string ] any
json. NewDecoder ( res. Body). Decode (& run)
fmt. Println ( run[ "id" ], run[ "status" ])
}
Response
202 Accepted
Copy
{
"id" : "8f14e45f-ceea-467a-9c2e-1b0f5a4c7d21" ,
"status" : "queued" ,
"platform" : "youtube" ,
"endpoint" : "search" ,
"target" : "mars rover" ,
"url" : "https://www.youtube.com/results?search_query=mars+rover" ,
"result_count" : 0 ,
"created_at" : "2026-08-27T17:55:24Z"
}
This endpoint errs towards returning more rather than less, so expect a few extra rows alongside what you asked for. Everything still comes back typed and parsed the same way.