# LinkedIn Profile Activity Time Scraper (`automation-lab/linkedin-profile-recent-activity-time`) Actor

Inspect public LinkedIn profiles and export the latest observed public activity timestamp, activity URL and type, observation time, and explicit status.

- **URL**: https://apify.com/automation-lab/linkedin-profile-recent-activity-time.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 2 total users, 1 monthly users, 78.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.52 / 1,000 item extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Profile Activity Time Scraper

Turn a list of known prospects into a current **linkedin profile activity time** snapshot. The Actor inspects supplied public LinkedIn people profiles and writes one structured observation per unique profile: the latest public activity timestamp, canonical activity URL, activity type, observation time, and an explicit status.

No LinkedIn login or customer cookies are required. The Actor uses Apify Residential Proxy sessions because LinkedIn does not reliably deliver public profile pages over direct or datacenter traffic.

### What does this LinkedIn activity scraper do?

For every supplied public profile URL, the Actor:

1. normalizes the profile URL;
2. opens the public recent-activity surface with a bounded, coherent session;
3. reads structured public activity metadata;
4. selects the newest observed activity;
5. records when the observation happened; and
6. distinguishes activity found, no activity observed, and access failure.

It does not discover people, log in to LinkedIn, or return a complete historical activity feed.

### Who is it for?

- **SDRs and sales operations teams** prioritizing prospects who recently published public content.
- **Recruiters** deciding when to follow up with known candidates.
- **CRM operators** adding an observation timestamp and activity signal to existing lead records.
- **RevOps analysts** comparing scheduled snapshots in a spreadsheet, warehouse, or automation.
- **Developers and AI agents** that need a typed, API-friendly result instead of a human-facing profile page.

### Why use it?

The output is profile-level and workflow-ready. You do not need to download a full post history just to answer “when was public activity last observed?”

Important reliability details are explicit:

- `no_activity_observed` means a usable public page was inspected but no supported activity record was found;
- `access_failed` means LinkedIn did not return a usable public page after bounded session rotation;
- a challenge page is never mislabeled as “no activity”; and
- duplicate profile URLs are processed once.

### What data does it extract?

| Field | Meaning |
| --- | --- |
| `profileUrl` | Canonical public LinkedIn profile URL |
| `profileSlug` | Slug parsed from the supplied profile URL |
| `status` | `activity_found`, `no_activity_observed`, or `access_failed` |
| `hasActivity` | `true`, `false`, or `null` when access failed |
| `latestActivityAt` | Latest exposed ISO 8601 activity timestamp |
| `latestActivityAge` | Relative age text when only a relative value is exposed |
| `activityUrl` | Canonical URL of the latest observed activity |
| `activityType` | Normalized type such as `post` or `article` |
| `observedAt` | Time at which this profile was inspected |
| `sourceUrl` | Public LinkedIn activity surface requested |
| `httpStatus` | Final upstream HTTP status when available |
| `error` | Concise access error, otherwise `null` |

All activity fields can be null when LinkedIn does not expose them. Use `status` and `hasActivity` before filtering by a timestamp.

### How to get started

1. Open the Actor input page.
2. Add one or more public URLs in `profileUrls`.
3. Keep `US` as the proxy country unless your workflow requires another supported country.
4. Set `maxItems` to the maximum number of unique profile observations needed.
5. Run the Actor.
6. Open the default dataset or export it as JSON, CSV, Excel, XML, RSS, or JSONL.
7. Sort successful observations by `latestActivityAt` for outreach prioritization.

### Input parameters

#### `profileUrls` (required)

An array of public LinkedIn people profile URLs. Both strings and Apify request-list objects are accepted by the Actor. Only URLs matching `linkedin.com/in/<slug>` are supported.

```json
{
  "profileUrls": [
    { "url": "https://www.linkedin.com/in/ajjames" },
    { "url": "https://www.linkedin.com/in/satyanadella" }
  ]
}
```

#### `maxItems`

Maximum number of unique profile observations written during one run. The default is 100 and the allowed range is 1–5,000.

#### `proxyCountryCode`

Two-letter country code for Apify Residential Proxy. The tested default is `US`. The Actor does not expose a direct or unmeasured automatic proxy fallback.

### Example input

```json
{
  "profileUrls": [
    { "url": "https://www.linkedin.com/in/ajjames" }
  ],
  "maxItems": 1,
  "proxyCountryCode": "US"
}
```

### Example output

This representative record is based on the current local implementation:

```json
{
  "profileUrl": "https://www.linkedin.com/in/ajjames/",
  "profileSlug": "ajjames",
  "status": "activity_found",
  "hasActivity": true,
  "latestActivityAt": "2026-02-03T00:14:35.000+00:00",
  "latestActivityAge": null,
  "activityUrl": "https://www.linkedin.com/pulse/speed-becoming-liability-taste-advantage-anthony-j-james-4pyif",
  "activityType": "article",
  "observedAt": "2026-08-30T06:09:25.843Z",
  "sourceUrl": "https://www.linkedin.com/in/ajjames/recent-activity/all/",
  "httpStatus": 200,
  "error": null
}
```

The source can change after this documentation is written. Always treat `observedAt` as the freshness boundary.

### How much does it cost to inspect LinkedIn profiles?

The Actor uses pay per event:

- a **$0.005 start event** once per run; and
- one **profile observation event** for each completed public profile observation.

The provisional BRONZE profile-observation price is **$0.0092 per completed profile**. Failed-access records are useful diagnostics but do not emit the profile-observation charge.

For a BRONZE run, calculate the total as the start event plus the number of completed profiles multiplied by the BRONZE profile-observation event. Tier pricing can lower the per-profile event price for higher subscription tiers.

Apify platform usage and proxy traffic are included in the Store pay-per-event experience when the Actor is run from the Store; always review the live pricing tab before a large run.

### Outreach-prioritization workflow

1. Export target profile URLs from your CRM.
2. Run this Actor on the list.
3. Keep rows with `status = activity_found`.
4. Sort by `latestActivityAt` descending.
5. Join the results to CRM records using `profileUrl`.
6. Route recently active prospects into a timely, human-reviewed outreach sequence.

The Actor reports a public signal. It does not determine intent, availability, or willingness to be contacted.

### Recurring monitoring workflow

Schedule the same Task daily or weekly and store each dataset with its `observedAt` value. Compare the newest snapshot with the previous snapshot to identify a changed `activityUrl` or `latestActivityAt`.

The Actor does not maintain history or send alerts itself. Use Apify schedules, webhooks, Make, Zapier, Google Sheets, or your warehouse to retain and compare snapshots.

### API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~linkedin-profile-recent-activity-time/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "profileUrls": [{"url": "https://www.linkedin.com/in/ajjames"}],
    "maxItems": 1,
    "proxyCountryCode": "US"
  }'
```

Never commit your Apify token to source control.

### API with JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/linkedin-profile-recent-activity-time').call({
  profileUrls: [{ url: 'https://www.linkedin.com/in/ajjames' }],
  maxItems: 1,
  proxyCountryCode: 'US',
});

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

### API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/linkedin-profile-recent-activity-time").call(
    run_input={
        "profileUrls": [{"url": "https://www.linkedin.com/in/ajjames"}],
        "maxItems": 1,
        "proxyCountryCode": "US",
    }
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with MCP and AI agents

Add the Actor-specific Apify MCP endpoint to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/linkedin-profile-recent-activity-time"
```

#### Claude Desktop

Add this server object to the Claude Desktop MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/linkedin-profile-recent-activity-time"
    }
  }
}
```

#### Cursor

Add the same `apify` server under **Settings → MCP** in Cursor.

#### VS Code

Add the same Actor-specific URL to your VS Code MCP server configuration. Your client opens the Apify OAuth flow the first time it connects.

Example prompts:

- “Inspect these public LinkedIn profile URLs and rank successful observations by latest activity time.”
- “Run a snapshot for this prospect list and return only profiles with a newly observed activity URL.”
- “Export access failures separately so I can retry them later.”

### Integrations

- **Google Sheets:** append one observation row per profile and sort by timestamp.
- **Make or Zapier:** trigger the Actor from a new CRM list and continue when the run finishes.
- **Webhooks:** notify an internal pipeline when a scheduled snapshot completes.
- **Warehouses:** retain `profileUrl`, `latestActivityAt`, and `observedAt` for historical comparisons.
- **CRM enrichment:** join by canonical profile URL and preserve the observation status.

### Limits and failure behavior

LinkedIn controls public delivery and can change page structure without notice. Public visibility also varies by profile and geography.

- The Actor requires Apify Residential Proxy access.
- It supports public people profile URLs, not company, school, job, search, or Sales Navigator URLs.
- It reports only activity exposed on the public page; it cannot prove that a person has no private or unexposed activity.
- `no_activity_observed` is an observation, not a claim that no activity exists anywhere.
- `access_failed` is not charged as a completed profile observation.
- Repeated URLs are deduplicated within the run.
- A timestamp may be null when LinkedIn exposes only relative age text.
- Deleted or visibility-restricted activities may disappear between runs.

### Tips for reliable runs

- Supply canonical `https://www.linkedin.com/in/...` profile URLs.
- Keep `US` unless a specific supported geography is important to your workflow.
- Use moderate batches and rerun only `access_failed` rows instead of blindly repeating the full list.
- Store `observedAt` with every downstream record.
- Do not interpret a publication timestamp as proof of current buying intent.

### Responsible use and legality

Use the Actor only for lawful purposes and data you are permitted to process. Public accessibility does not remove obligations under privacy, data-protection, employment, anti-spam, contractual, or sector-specific rules.

Follow LinkedIn's applicable terms and local law. Minimize collected data, define a retention period, secure exports, honor relevant rights requests, and keep consequential outreach or recruiting decisions under human review. Do not use this Actor for harassment, surveillance, discrimination, or attempts to access non-public information.

### Frequently asked questions

#### Does it require LinkedIn cookies or a login?

No customer cookies or LinkedIn account are required. The Actor uses bounded public-page sessions through Apify Residential Proxy.

#### Does it return all posts, comments, and reactions?

No. It returns a profile-level latest observed public activity signal. For recent public post records, use the related LinkedIn Profile Posts Scraper.

#### What does `no_activity_observed` mean?

A usable public page was inspected, but no supported public activity record was found. It does not prove that the person has never been active.

#### Why did I receive `access_failed`?

LinkedIn returned a challenge, an unusable page, or no response after bounded session rotation. Retry that row later. The Actor keeps access failure distinct from no activity and does not charge it as a completed observation.

#### Can I schedule recurring checks?

Yes. Save the input as an Apify Task, attach a schedule, and retain each run's dataset. Comparison and alerting are downstream workflow steps rather than built-in history.

#### Why is the latest activity timestamp null?

LinkedIn may expose only relative age text on some public surfaces. In that case, inspect `latestActivityAge`. If both fields are null, check `status` and `error`.

### Related automation-lab Actors

- [LinkedIn Profile Posts Scraper](https://apify.com/automation-lab/linkedin-profile-posts-scraper) — extract recent public posts and articles when you need post-level records.
- [LinkedIn Public People Profile Scraper](https://apify.com/automation-lab/linkedin-public-people-profile-scraper) — enrich known public profile URLs with identity and career fields exposed publicly.
- [LinkedIn Profile URL Finder](https://apify.com/automation-lab/linkedin-profile-url-finder) — resolve known people to likely public profile URLs before activity inspection.

### Support

When reporting a problem, include a redacted input, run URL, affected profile URL if it is safe to share, expected status, and observed status. Do not include Apify tokens, private cookies, or confidential CRM data.

# Actor input Schema

## `profileUrls` (type: `array`):

Public LinkedIn people profile URLs to inspect. Duplicate profile URLs are processed once.

## `maxItems` (type: `integer`):

Maximum number of unique profile observation records to write in this run.

## `proxyCountryCode` (type: `string`):

Two-letter country code for the Residential Proxy session used to open public LinkedIn pages. US is the tested default.

## Actor input object example

```json
{
  "profileUrls": [
    {
      "url": "https://www.linkedin.com/in/ajjames"
    }
  ],
  "maxItems": 10,
  "proxyCountryCode": "US"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Structured records with activity timestamps, URLs, types, observation times, and explicit statuses.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "profileUrls": [
        {
            "url": "https://www.linkedin.com/in/ajjames"
        }
    ],
    "maxItems": 10,
    "proxyCountryCode": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/linkedin-profile-recent-activity-time").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "profileUrls": [{ "url": "https://www.linkedin.com/in/ajjames" }],
    "maxItems": 10,
    "proxyCountryCode": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/linkedin-profile-recent-activity-time").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "profileUrls": [
    {
      "url": "https://www.linkedin.com/in/ajjames"
    }
  ],
  "maxItems": 10,
  "proxyCountryCode": "US"
}' |
apify call automation-lab/linkedin-profile-recent-activity-time --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/linkedin-profile-recent-activity-time"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/TPSj0XaYvxzskxwaV/builds/Zsx2LUhnyZoptPbG8/openapi.json
