Skip to main content

Overview

Fetchin exposes an Apify-compatible endpoint. If you already run B2B data actors through Apify, you can keep your existing code and the official Apify client libraries — you only change the base URL to Fetchin and use your Fetchin API key as the token. Everything runs asynchronously, exactly like Apify: you start an actor run, we queue it, and you poll for the result and read the dataset. Batches are buffered and drained at your plan’s RPS.

Base URL

https://api.fetchin.io/v1/apify
Point any Apify client at that base URL and pass your Fetchin API key as the token. That’s the whole change.

Supported actors

The following Apify actors are supported today. Reference an actor by its raw actor ID or by the username/actor-name form your existing integration already uses — both resolve.
Apify actorActor IDWhat it returns
supreme_coder/linkedin-profile-scraperyZnhB5JewWf9xSmoMA full professional profile (one item per profile). Input scrapeCompany: true adds the current-company block.
supreme_coder/linkedin-postWpp1BZ6yGWjySadk3A profile’s posts. Input deepScrape: true adds reactions + comments per post.
apimaestro/linkedin-profile-comments7TNcROe1C2CQDO3wlComments made by a profile (paginated).
apimaestro/linkedin-profile-reactionsFNhKFjeL8hWQtMeZIReactions made by a profile (paginated).
We map the output fields to match each actor as closely as possible, so your downstream code keeps working unchanged.
Need another actor? If you rely on an actor that isn’t in this list, reach out via the chat on fetchin.io or email us — we add actors on request.

Usage

JavaScript / Node (apify-client)

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({
  token: process.env.FETCHIN_API_KEY,
  baseUrl: 'https://api.fetchin.io/v1/apify', // the only change
});

// Start a run and wait for it to finish
const run = await client
  .actor('yZnhB5JewWf9xSmoM')
  .call({ urls: [{ url: 'https://www.linkedin.com/in/williamhgates/' }], scrapeCompany: true });

// Read the dataset
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python (apify-client)

from apify_client import ApifyClient
import os

client = ApifyClient(
    token=os.environ["FETCHIN_API_KEY"],
    api_url="https://api.fetchin.io/v1/apify",  # the only change
)

run = client.actor("yZnhB5JewWf9xSmoM").call(
    run_input={"urls": [{"url": "https://www.linkedin.com/in/williamhgates/"}], "scrapeCompany": True}
)

items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)

HTTP (any language)

# 1. Start a run
curl -s -X POST \
  'https://api.fetchin.io/v1/apify/v2/acts/yZnhB5JewWf9xSmoM/runs' \
  -H 'Authorization: Bearer '"$FETCHIN_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"urls":[{"url":"https://www.linkedin.com/in/williamhgates/"}],"scrapeCompany":true}'
# -> { "data": { "id": "<runId>", "defaultDatasetId": "<datasetId>", "status": "READY", ... } }

# 2. Poll the run until status is SUCCEEDED (waitForFinish long-polls up to 60s)
curl -s \
  'https://api.fetchin.io/v1/apify/v2/actor-runs/<runId>?waitForFinish=60' \
  -H 'Authorization: Bearer '"$FETCHIN_API_KEY"

# 3. Read the dataset (a JSON array of items)
curl -s \
  'https://api.fetchin.io/v1/apify/v2/datasets/<datasetId>/items' \
  -H 'Authorization: Bearer '"$FETCHIN_API_KEY"

Pagination (comments & reactions)

The paginated actors return one page per run. To page, re-run the actor with the pagination_token from the previous page’s items and an incremented page_number — exactly as with Apify:
let pageNumber = 1;
let token = null;
do {
  const run = await client
    .actor('FNhKFjeL8hWQtMeZI')
    .call({ username: 'williamhgates', page_number: pageNumber, pagination_token: token });
  const { items } = await client.dataset(run.defaultDatasetId).listItems();
  // ... process items ...
  token = items[0]?.pagination_token ?? null;
  pageNumber += 1;
} while (token);
A profile with no reactions returns a single sentinel item { "message": "No reaction found for this profile" }, matching Apify.

Billing, timeouts & retention

  • Billing: 1 dataset item = 1 Fetchin credit (the same per-result accounting as Apify). A batch of 25 profiles = 25 credits. Exception: a post fetched with deepScrape: true costs 3 credits per post — the post itself plus the two extra requests for its comments and its reactions. A shallow post (deepScrape: false / omitted) costs 1 credit.
  • Timeout: the timeout input (seconds) bounds a run. If it elapses, the run ends TIMED-OUT and the items already produced remain in the dataset.
  • Retention: run records and datasets are retained for 24 hours. Fetch your results within that window.
  • Rate: your account RPS controls how fast we drain your queued items (not how many runs you can create). Creating runs far faster than your RPS returns 429 with Retry-After; the Apify client backs off automatically.

Differences vs Apify

We validate every actor against real Apify output field-by-field. The reactions, comments and post actors reach zero field errors on matched items; the differences below are values that either cannot be reproduced byte-for-byte (live counts, signed URLs, per-request tokens) or that we approximate where the source data isn’t exposed. Everything here is stable and documented so you can decide whether it affects your integration. If a specific field blocks you, contact us and we’ll prioritise it.

Applies to all actors

  • Live engagement counts (reactions/comments/reposts totals) drift second to second — they reflect the source at fetch time, so two fetches rarely match to the digit. This is identical to Apify.
  • Relative timestamps ("15h", "2w") are wall-clock-relative to the moment of the request. Absolute timestamps (timestamp, postedAtISO, formatted) are exact.
  • Signed media URLs carry an expiring signature (?e=…&v=…&t=…). The host + path are stable; the signature differs every request.
  • Pagination tokens are opaque and positional — use them, don’t compare them.

supreme_coder/linkedin-profile-scraper (profile)

FieldDifference
currentCompanyWith scrapeCompany: true we return a compact block (name, universalName, url). Apify’s full company sub-tree (employee counts, industries, HQ, affiliated pages…) is not fully reproduced yet.
pictureUrl, coverImageUrl, logosDimension-keyed objects ({"800x800": "…"}). We currently populate the largest rendition keyed by its real size; other size keys may be absent.
courses, honors, volunteerExperiences, projects, publications, patents, testScores, organizations, certifications, languages, volunteerCausesReturned as [] (extraction of these sections is in progress).
mutualConnectionsAlways [] — depends on the viewer’s network and isn’t available to a service account.
fullNameDerived as firstName + " " + lastName.

supreme_coder/linkedin-post (post)

FieldDifference
author.id, authorUrnThe numeric member id / member-scheme urn isn’t present in the source feed. We return the public handle (author.publicId, authorProfileId) and the profile id (author.profileId).
author.trackingId, author.backgroundImageNot reproduced (per-request token / not in the feed).
resharedPostReshared posts are not nested. The underlying feed returns a profile’s own posts; pure reshares are filtered.
urlCanonical post permalink. The trailing ?rcm=… token is per-viewer and will differ.
linkedinVideo.videoPlayMetadataCore fields (streams, duration, thumbnail, aspect ratio) are reproduced; transcripts, adaptiveStreams and trackingId are omitted.
attributes, comment entitiesInline @mention / hashtag annotation ranges are returned as [].
Deep comments[] / reactions[]These are relevance-ranked live lists — the exact top-N set differs between any two fetches (true on Apify too). Per engager: firstName/lastName are split best-effort from the display name (Apify uses the source’s structured name fields); publicId is the profile id (the engager lockup doesn’t expose the handle); id, trackingId, backgroundImage, distance, originalLanguage are omitted. Names, occupation, picture and profileId match.

apimaestro/linkedin-profile-comments (comments)

  • Full field parity on matched items. Only the volatile values above (live comment/post reaction counts, relative time) differ.
  • Items do not carry a root pagination_token — this actor pages by page_number (this matches Apify’s actor).

apimaestro/linkedin-profile-reactions (reactions)

FieldDifference
actionWe return the reaction type enum (LIKE, EMPATHY, APPRECIATION, INTEREST, PRAISE, ENTERTAINMENT). Apify emits a header sentence (e.g. "Bill Gates likes this"). Tell us if you need the sentence form.
post_urlThe canonical post permalink — same post, may be a different valid URL form than Apify’s.
post_stats per-type countsReproduced (like/appreciation/empathy/interest/praise), subject to the live-count drift noted above.