Collect profiles from posts
Collect LinkedIn profiles of people who reacted to or commented on selected posts and save the results to a new List in Woodpecker.
This request creates a collector for each post and selected engagement type. Processing is asynchronous - use list collection jobs or get a collection job to check progress.
Each request creates one List containing the collected profile URLs, post URLs, reaction types, and comment text. Open it in Woodpecker to work with the results.
Request
This request can use account credits. Collecting profiles from reactions costs 1 credit per 100 profiles (0.01 credit per profile), while collecting profiles from comments costs 3 credits per 100 profiles (0.03 credit per profile). Credits are used only for profiles that are successfully collected. GET endpoints used to check collection status do not use credits.
Most collection jobs complete within 5-10 minutes. Check progress using either GET endpoint. Submitting the same post and source again does not speed up collection and may be rejected while a matching collector is still active.
Endpoint
POST https://api.woodpecker.co/rest/v2/linkedin/post_profiles_collectors/enqueue
Headers
x-api-key: {YOUR_API_KEY}
Content-Type: application/json
For details on how to authenticate your requests, please see the authentication guide.
Body
Submit up to 100 unique LinkedIn post URLs. In collect_from, set comments, reactions, or both to true. Both options save the LinkedIn profile URL and post URL to the new list. Reaction collection also saves the reaction type, while comment collection saves the comment text.
{
"post_urls": [
"https://www.linkedin.com/posts/linkedin_post_url"
],
"collect_from": {
"comments": true,
"reactions": true
},
"target_new_list_name": "ICP profiles"
}
Body schema
| Field | Type | Required | Description |
|---|---|---|---|
post_urls | array[string] | Yes | 1 to 100 unique LinkedIn post URLs. Each URL must start with https://www.linkedin.com/posts/ |
collect_from | object | Yes | Sources from which profiles should be collected |
└─ comments | boolean | Yes | Set to true to collect profiles that commented on the posts, together with their comment text |
└─ reactions | boolean | Yes | Set to true to collect profiles that reacted to the posts, together with their reaction type |
target_new_list_name | string | Yes | Base name for the new list; Woodpecker appends - LinkedIn Leads at the end |
Request samples
Collect profiles from comments and reactions
- cURL
- Python
- Java
- Node.js
- PHP
curl --request POST \
--url "https://api.woodpecker.co/rest/v2/linkedin/post_profiles_collectors/enqueue" \
--header "x-api-key: {YOUR_API_KEY}" \
--header "Content-Type: application/json" \
--data '{
"post_urls": [
"https://www.linkedin.com/posts/linkedin_post_url"
],
"collect_from": {
"comments": true,
"reactions": true
},
"target_new_list_name": "Pied Piper post engagement"
}'
import requests
def enqueue_post_profile_collectors():
url = "https://api.woodpecker.co/rest/v2/linkedin/post_profiles_collectors/enqueue"
headers = {
"x-api-key": "{YOUR_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"post_urls": [
"https://www.linkedin.com/posts/linkedin_post_url"
],
"collect_from": {
"comments": True,
"reactions": True
},
"target_new_list_name": "Pied Piper post engagement"
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 202:
return response.json()
raise Exception(f"POST request failed: {response.status_code}, {response.text}")
if __name__ == "__main__":
try:
print("POST response:", enqueue_post_profile_collectors())
except Exception as error:
print("Error:", error)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class WoodpeckerApiClient {
public static void main(String[] args) {
try {
String url = "https://api.woodpecker.co/rest/v2/linkedin/post_profiles_collectors/enqueue";
String jsonData = """
{
"post_urls": [
"https://www.linkedin.com/posts/linkedin_post_url"
],
"collect_from": {
"comments": true,
"reactions": true
},
"target_new_list_name": "Pied Piper post engagement"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(url))
.header("x-api-key", "{YOUR_API_KEY}")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonData))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 202) {
System.out.println("POST response: " + response.body());
} else {
throw new RuntimeException(
"POST request failed: " + response.statusCode() + ", " + response.body()
);
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
const axios = require("axios");
async function enqueuePostProfileCollectors() {
const url = "https://api.woodpecker.co/rest/v2/linkedin/post_profiles_collectors/enqueue";
const headers = {
"x-api-key": "{YOUR_API_KEY}",
"Content-Type": "application/json"
};
const data = {
post_urls: [
"https://www.linkedin.com/posts/linkedin_post_url"
],
collect_from: {
comments: true,
reactions: true
},
target_new_list_name: "Pied Piper post engagement"
};
try {
const response = await axios.post(url, data, { headers });
console.log("POST response:", response.data);
} catch (error) {
console.error(
"POST request failed:",
error.response ? error.response.status : error.message
);
}
}
enqueuePostProfileCollectors();
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
'base_uri' => 'https://api.woodpecker.co/rest/v2/',
'headers' => [
'x-api-key' => getenv('WOODPECKER_API_KEY'),
'Content-Type' => 'application/json',
],
]);
try {
$response = $client->post('linkedin/post_profiles_collectors/enqueue', [
'json' => [
'post_urls' => [
'https://www.linkedin.com/posts/linkedin_post_url',
],
'collect_from' => [
'comments' => true,
'reactions' => true,
],
'target_new_list_name' => 'Pied Piper post engagement',
],
]);
echo $response->getStatusCode(), "\n";
echo $response->getBody(), "\n";
} catch (RequestException $e) {
echo "Error: ", $e->getMessage(), "\n";
if ($e->hasResponse()) {
echo $e->getResponse()->getBody(), "\n";
}
}
Response
Response examples
- 202
- 400
- 401
- 422
- 500
The collectors were accepted for processing. Each object represents one post and one source. Store each collector_uid and use get a collection job to check its status
{
"accepted_posts": [
{
"collector_uid": "e9e6abc4-799e-4c24-b412-7927b1db919d",
"post_url": "https://www.linkedin.com/posts/linkedin_post_url",
"target_list_uid": "5f17c0d2-5100-4bb9-a312-fe17f27f94c1",
"collect_from": "REACTIONS"
},
{
"collector_uid": "caf15107-53dc-4f19-8920-ddfbd95b44c3",
"post_url": "https://www.linkedin.com/posts/linkedin_post_url",
"target_list_uid": "5f17c0d2-5100-4bb9-a312-fe17f27f94c1",
"collect_from": "COMMENTS"
}
]
}
Body schema
| Field | Type | Description |
|---|---|---|
accepted_posts | array[object] | Collectors accepted for asynchronous processing |
└─ collector_uid | string | Collector UUID to use with the get endpoint |
└─ post_url | string | LinkedIn post URL submitted for this collector |
└─ target_list_uid | string | UUID of the new List shared by all collectors from this request |
└─ collect_from | string | Collection source: REACTIONS or COMMENTS |
Returned when the request body is missing, is not valid JSON, or omits a required field
{
"type": "validation_error",
"code": "invalid_fields",
"message": "Invalid field(s)",
"requestId": "4a3cc945-f502-4f83-b0ee-5d7fd1f38548",
"fields": [
{
"field": "post_urls",
"issue": "required",
"value": null
}
]
}
Body schema
| Field | Type | Description |
|---|---|---|
type | string | Error type: validation_error |
code | string | Error code: invalid_fields |
message | string | Human-readable error summary |
requestId | string/null | Request identifier, or null when unavailable |
fields | array[object] | Invalid or missing request fields |
└─ field | string | Field path, such as body, post_urls, collect_from.comments, etc |
└─ issue | string | Shape error: required or invalid |
└─ value | any/null | Rejected value, or null when no value was supplied |
An issue with authorization. Please review the authorization guide
{
"title": "Unauthorized",
"status": 401,
"detail": "Invalid api key",
"timestamp": "2026-08-05 10:00:00"
}
Body schema
| Field | Type | Description |
|---|---|---|
title | string | A short title describing the error |
status | integer | The HTTP status code |
detail | string | A detailed message explaining the error |
timestamp | string | The timestamp when the error occurred |
Returned when the request body contains invalid field values. The following example shows an empty post_urls array.
{
"type": "validation_error",
"code": "invalid_fields",
"message": "Invalid field(s)",
"requestId": "80820418-a95c-4b37-9fd3-68a4c9d7e6a0",
"fields": [
{
"field": "post_urls",
"issue": "empty",
"value": []
}
]
}
Body schema
| Field | Type | Description |
|---|---|---|
type | string | Error type |
code | string | Error code |
message | string | Error message |
requestId | string/null | Request identifier when available |
fields | array[object] | Fields that failed validation |
└─ field | string | Field with a validation issue |
└─ issue | string | Validation issue: empty, too_many, invalid format, expected: ..., duplicated, already_exists, at_least_one_required, or required |
└─ value | any/null | Rejected value, or null when unavailable |
Unexpected error, please try again later
{
"type": "internal_error",
"code": "internal_server_error",
"message": "An unexpected error occurred on the server.",
"requestId": "4a3cc945-f502-4f83-b0ee-5d7fd1f38548"
}
Body schema
| Field | Type | Description |
|---|---|---|
type | string | Error type: internal_error |
code | string | Error code: internal_server_error |
message | string | Human-readable error summary |
requestId | string/null | Request identifier, or null when unavailable |