# SEC Schedule 13D/13G: activist and 5% stakes, every person (`johnveds15/sec-13d-13g-ownership-stakes`) Actor

Every Schedule 13D/13G on EDGAR, from the SEC's own XML: each reporting person as a row (type, percent, shares, voting power), issuer CUSIP + tickers, the 13D's Item 4 purpose text with flags, isActivist for a NEW 13D. No browser, no proxy.

- **URL**: https://apify.com/johnveds15/sec-13d-13g-ownership-stakes.md
- **Developed by:** [John Vedovino II](https://apify.com/johnveds15) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 schedule 13d/13g filings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SEC Schedule 13D/13G — activist & 5% stakes, every reporting person

**Every Schedule 13D and 13G filed on EDGAR in your window, parsed from the SEC's own XML — each reporting person as its own row with percent of class, shares and voting power, the issuer's CUSIP and tickers, the 13D's Item 4 "Purpose of Transaction" text with purpose flags, and `isActivist` for a new 13D. No browser, no proxy, no paid data, no start fee.**

A Schedule 13D is the filing a holder must make within five business days of crossing 5% of a class **with intent** — activists, acquirers, control groups. A 13G is the passive version — index funds, advisers, banks. Since the SEC's structured-data rule (December 2024) both are filed as XML, so the cover page and the numbered items are fields. This Actor reads those fields; the multi-form scrapers that list "13D/G" still scrape the HTML rendering.

### What you get that a summary-table scraper doesn't

| Field | Why it matters |
|---|---|
| `reportingPersons[]` | **Every** person on the cover page, not just the first: name, CIK, SEC type code decoded (`IA` investment adviser, `HC` parent holding company, `IN` individual, `PN` partnership …), percent of class, aggregate shares, sole/shared voting and dispositive power, citizenship. A joint filing by a fund, its GP and its founder is three rows. |
| `isActivist` | `true` for an **original** Schedule 13D — not an amendment, not a 13G. The 4-8 filings a day that say someone crossed 5% on purpose. |
| `purposeOfTransaction` + `purposeFlags` | The 13D's Item 4 text (first 2,000 chars) and deterministic flags over it: `board`, `proxy`, `nominate`, `merger`, `strategic-alternatives`, `management-change`, `capital-return`, `engage`, `financing`. Keyword rules, listed below — no model, same input same output. |
| `sourceOfFunds` | Item 3: working capital, margin, borrowed funds. |
| `eventDate`, `lagDays` | The date that triggered the filing vs the filed date. A 13D filed 22 days after the event is a fact worth having as a number. |
| `cusip`, `securityClass`, `tickers` | CUSIP and class from the filing itself; tickers from the SEC's `company_tickers.json`, so the CIK-to-ticker map is the SEC's. |
| `maxPercentOfClass`, `maxAggregateShares` | The largest reporting person's numbers, for a one-glance filter. |

### A real record

Produced from live EDGAR data on 2026-09-24 (a Schedule 13D filed 2026-09-23; person names shortened):

```json
{
  "type": "stake",
  "form": "SCHEDULE 13D",
  "schedule": "13D",
  "isAmendment": false,
  "isActivist": true,
  "accession": "0000921895-26-002628",
  "filedDate": "2026-09-23",
  "eventDate": "2026-09-18",
  "lagDays": 5,
  "issuerName": "URSB Bancorp, Inc.",
  "issuerCik": "0002045301",
  "tickers": ["URSB"],
  "cusip": "90323M102",
  "securityClass": "Common Stock, par value $0.01 per share",
  "personCount": 8,
  "maxPercentOfClass": 9.0,
  "reportingPersons": [
    {"name": "SEIDMAN & ASSOCIATES LLC ET AL", "cik": "0001000267", "typeCode": "OO", "type": "other", "percentOfClass": 2.2, "aggregateShares": 51642.0,
     "soleVoting": 51642.0, "sharedVoting": 0.0, "soleDispositive": 51642.0, "sharedDispositive": 0.0, "citizenship": "NJ"},
    {"name": "…", "typeCode": "IN", "type": "individual", "percentOfClass": 9.0, "aggregateShares": 209940.0, "…": "…"}
  ],
  "purposeOfTransaction": "The Reporting Persons originally purchased the Shares based on the Reporting Persons' belief that the Shares, when purchased, were undervalued …",
  "purposeFlags": ["board", "engage"],
  "sourceOfFunds": "The Shares purchased by the Reporting Persons were purchased with working capital …",
  "primaryDocUrl": "https://www.sec.gov/Archives/edgar/data/1026081/000092189526002628/primary_doc.xml",
  "filingIndexUrl": "https://www.sec.gov/Archives/edgar/data/1026081/000092189526002628/0000921895-26-002628-index.htm"
}
```

### Input

| Field | Default | Notes |
|---|---|---|
| `secContactEmail` | — | **Required.** Sent in the User-Agent to sec.gov only. EDGAR returns 403 without it. |
| `lookbackDays` | 3 | Calendar days of daily indices back from `endDate`. Weekends/holidays are skipped. |
| `endDate` | today | `YYYY-MM-DD`. |
| `schedules` | both | `["13D"]`, `["13G"]` or empty. |
| `includeAmendments` | true | 13D/A and 13G/A carry `isAmendment: true`. |
| `activistOnly` | false | Only original 13Ds (`isActivist`). Implies `schedules=["13D"]`, no amendments. |
| `tickers` | any | Issuer tickers per the SEC's map. |
| `minPercentOfClass` | 0 | Largest reporting person must hold at least this percent. |
| `purposeFlags` | any | Keep 13Ds whose Item 4 carries one of the flags. |
| `maxFilings` | 150 | Newest first. Bounds runtime and cost. |

Legacy `SC 13D` / `SC 13G` (HTML-only, pre-2025) are skipped and counted in the run summary as `legacyHtmlSkipped`.

### Purpose flags — the rules

Case-insensitive regular expressions over Item 4. `board`: board / director(s) · `proxy`: proxy, solicit · `nominate`: nominat… · `merger`: merger, acquire/acquisition, tender offer · `strategic-alternatives`: "strategic alternatives", "sale of the company/issuer", going private · `management-change`: management within 60 chars of change/replace/remove · `capital-return`: buyback, repurchase, dividend, capital allocation · `engage`: engage, discussion(s), communicat… · `financing`: financ…, loan, credit. A flag is a pointer to the text, not a verdict.

### Pricing

No start fee. You pay per event, so the bill tracks what the run actually did:

| Event | Price | Charged when |
|---|---|---|
| Schedule 13D/13G filing | $0.001 | per schedule whose XML was fetched and parsed. Errors are not charged. |
| Ownership stake record delivered | $0.001 | per record pushed after your filters. |
| New Schedule 13D (activist stake) delivered | $0.02 | per original 13D record delivered — the output you came for. |

**Worked examples, in cents.** A full day (about 50 schedules, 4-8 new 13Ds): 50 × 0.1¢ + 50 × 0.1¢ + 6 × 2¢ = **22¢**. `activistOnly` for a day: 6 parsed + 6 records + 6 activist = **13¢**. A month of daily activist runs is about **$3**. Apify platform usage is billed separately and is small: this is a plain Python container with no browser.

### SEC fair access

Requests carry your contact address and are paced at about 7.5 per second, under the SEC's published limit of 10. Neither is configurable, by design.

### Output

Dataset: one record per filing (view **Ownership stakes**). Key-value store `SUMMARY`: `filingsIndexed`, `legacyHtmlSkipped`, `filingsParsed`, `parseOutcomes`, `recordsPushed`, `activistPushed`, and the per-event counts charged. Run it locally with `python -m src.main` — the parser is plain Python (`requests` + `lxml`).

# Actor input Schema

## `secContactEmail` (type: `string`):

The SEC's fair-access policy requires every automated request to identify its sender. This address is placed in the User-Agent header and is sent ONLY to sec.gov. EDGAR returns 403 without it.

## `lookbackDays` (type: `integer`):

How many calendar days of EDGAR daily indices to sweep, counting back from End date. Weekends and federal holidays have no index and are skipped, not errors.

## `endDate` (type: `string`):

Last day of the window. Defaults to today.

## `schedules` (type: `array`):

13D = holders with intent (activists, acquirers, control persons); 13G = passive holders (index funds, advisers, banks). Empty = both.

## `includeAmendments` (type: `boolean`):

Amendments report changes to an existing stake. Each record carries isAmendment; a NEW 13D (not an amendment) carries isActivist=true.

## `activistOnly` (type: `boolean`):

Keep only original Schedule 13D filings — the record that says a holder crossed 5% with intent. Typically 4-8 a day.

## `tickers` (type: `array`):

Restrict to issuers whose ticker (per the SEC's company\_tickers.json) is in this list. Empty = every issuer.

## `minPercentOfClass` (type: `integer`):

Keep filings where the largest reporting person holds at least this percent of the class. 0 = keep all.

## `purposeFlags` (type: `array`):

board · proxy · nominate · merger · strategic-alternatives · management-change · capital-return · engage · financing. Derived from the Item 4 text by fixed keyword rules (listed in the README). Empty = no filter.

## `maxFilings` (type: `integer`):

Hard cap on schedules fetched this run (newest first). Bounds runtime and cost. Default 150 costs at most $0.30 in filing + record events plus $0.02 per new 13D delivered.

## Actor input object example

```json
{
  "secContactEmail": "you@example.com",
  "lookbackDays": 5,
  "schedules": [
    "13D"
  ],
  "includeAmendments": true,
  "activistOnly": true,
  "tickers": [],
  "minPercentOfClass": 0,
  "purposeFlags": [],
  "maxFilings": 300
}
```

# Actor output Schema

## `stakes` (type: `string`):

One record per Schedule 13D/13G kept by the filters: every reporting person with percent, shares and voting power; issuer CUSIP + tickers; the 13D's Item 4 purpose text and flags; isActivist for a new 13D.

## `summary` (type: `string`):

filingsIndexed, legacyHtmlSkipped, filingsParsed, parseOutcomes, recordsPushed, activistPushed, and the pay-per-event counts charged this run.

# 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 = {
    "secContactEmail": "you@example.com",
    "lookbackDays": 5,
    "schedules": [
        "13D"
    ],
    "activistOnly": true,
    "maxFilings": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("johnveds15/sec-13d-13g-ownership-stakes").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 = {
    "secContactEmail": "you@example.com",
    "lookbackDays": 5,
    "schedules": ["13D"],
    "activistOnly": True,
    "maxFilings": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("johnveds15/sec-13d-13g-ownership-stakes").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 '{
  "secContactEmail": "you@example.com",
  "lookbackDays": 5,
  "schedules": [
    "13D"
  ],
  "activistOnly": true,
  "maxFilings": 300
}' |
apify call johnveds15/sec-13d-13g-ownership-stakes --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,johnveds15/sec-13d-13g-ownership-stakes"
        }
    }
}
```

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/bsl87hd3aYrqJYtx0/builds/bgs01BTryCHlv8ZPU/openapi.json
