/api/v1/scrapping/form-13fScrape 13F-HR institutional-holdings filings for a specific CIK.
Scrape 13F-HR institutional-holdings filings for a specific CIK. Returns parsed filing metadata + the holdings information table (one row per portfolio position) with CUSIP-level enrichment (ticker, security name, FIGI). Use this for institutional-manager portfolio analysis when you need EDGAR-native field shapes; for the curated FinRadar 13F surface use /api/v1/13f/filer/{cik}/holdings.
Why use this
Common use case
Live 13F-HR institutional-holdings scraper — pass a manager CIK + optional date range, receive their most recent 13F-HR filings with full holdings tables. CUSIPs are server-side enriched via the local cusip_mappings table to add ticker, security_name, security_type, and FIGI codes. Heavy (10 tokens) because the Python subprocess fetches the index page + information-table XML, parses both, then enriches every CUSIP. For NEW integrations strongly prefer GET /api/v1/13f/filer/{cik}/holdings — the curated FinRadar 13F surface is faster, cheaper, returns split-adjusted positions, and includes percentage-of-portfolio + delta-from-prior-quarter columns out of the box. The scrapping endpoint is preserved for: (a) sec-api.io migration-compatibility (matches their response shape), (b) tutorial follow-along, (c) cases where you specifically need the EDGAR-native field names. Returns 13F-NT filings too (NT = no holdings) — these have empty holdings[] arrays. For institutional-manager analytics across multiple managers, see GET /api/v1/13f/holdings/by-cusip which pivots the same data CUSIP-first.
Parameters
| Name | In | Required | Default | Allowed | Description | Example |
|---|---|---|---|---|---|---|
| cik | query | required | — | — | Institutional manager CIK as a digit-only string, max 10 digits (e.g. `0001067983` for Berkshire Hathaway, `1364742` for BlackRock). Returns 400 BAD_REQUEST when missing or non-numeric. Resolve a manager name → CIK via [GET /api/v1/sec/entities?form_type=13F-HR](/docs/sec-filings/sec-filings-api/get-sec-entities). | 0001067983 |
| start_date | query | optional | — | — | Lower-bound filing date in `YYYY-MM-DD` format. Returns 400 on invalid format. Filtered at SEC level — reduces upstream load. | 2025-01-01 |
| end_date | query | optional | — | — | Upper-bound filing date in `YYYY-MM-DD` format. Returns 400 on invalid format. | 2025-12-31 |
| count | query | optional | 10 | — | Maximum number of 13F-HR filings to return (must be 1-40). Returns 400 outside that range. For quarterly tracking use `count=4` (last year); for full historical use `count=40` (which spans ~10 years for most managers). | 4 |
Response schema
| Field | Type | Nullable | Description |
|---|---|---|---|
| query | object | no | Echo of input parameters. |
| query.cik | string | no | Echoed CIK. |
| query.formType | string | no | Always `"13-F"` (note the dash — preserved from EDGAR's stored form, distinct from the canonical `13F-HR` used in the local index). |
| query.start_date | string | yes | Echoed start_date param. Null when omitted. |
| query.end_date | string | yes | Echoed end_date param. Null when omitted. |
| query.result | integer | no | Count of filings returned in `data` (when `data` is an array) or `1` (when `data` is a single filing object). |
| data | array | no | Array of 13F-HR filings, sorted by `filed_date DESC` (newest first). Each element is a parsed 13F filing with embedded holdings table — see `data[].*` for shape. Single-element when `count=1`; up to `count` elements otherwise. Empty array when no filings match — never null. |
| data[].accessionNo | string | no | SEC accession number in canonical 18-char dashed format `XXXXXXXXXX-YY-NNNNNN`. |
| data[].cik | string | no | Institutional manager CIK (echoes the input). |
| data[].companyName | string | no | Manager's legal entity name as registered with SEC (e.g. `BERKSHIRE HATHAWAY INC`). |
| data[].formType | string | no | Form type — `13F-HR` for the standard quarterly filing or `13F-HR/A` for amendments. NT-suffixed forms (`13F-NT`) appear here too — these have no information table to drill into. |
| data[].filingDate | string | no | ISO date `YYYY-MM-DD` of the filing's SEC acceptance date in ET. |
| data[].periodOfReport | string | no | ISO date `YYYY-MM-DD` of the as-of date for the holdings table (typically last day of the calendar quarter — `2025-03-31`, `2025-06-30`, `2025-09-30`, `2025-12-31`). |
| data[].linkToFilingDetails | string | no | SEC EDGAR URL for the filing's index page. |
| data[].linkToInformationTable | string | yes | Direct URL to the information-table XML file (the structured holdings list). Null on `13F-NT` filings which have no information table. |
| data[].holdings | array | no | Array of portfolio positions parsed from the information table. One row per `(CUSIP, security_class)` pair. Empty array on `13F-NT` filings or filings with empty information tables (rare but legitimate). |
| data[].holdings[].cusip | string | no | 9-character CUSIP identifier of the security held. |
| data[].holdings[].nameOfIssuer | string | no | Issuer name as reported in the information table (often differs cosmetically from the issuer's canonical name — dedupe via CUSIP not name). |
| data[].holdings[].titleOfClass | string | no | Security class (e.g. `COM`, `COM CL A`, `PUT`, `CALL`). |
| data[].holdings[].value | integer | no | Market value of the position in USD (NOT in thousands — server-side normalized from the 2022-09-onward `value_in_dollars` form). Rationale: pre-2022-09 13F filings reported `value` in USD-thousands; we convert client-side to a unified USD scale. |
| data[].holdings[].shares | integer | no | Share count held (or principal amount for debt instruments). |
| data[].holdings[].sshPrnamtType | string | no | Share/principal type — `SH` (shares) or `PRN` (principal amount). Distinguishes equity holdings from debt holdings. |
| data[].holdings[].putCall | string | yes | Option type for derivative positions — `PUT` or `CALL`. Null on direct equity holdings (the most common case). |
| data[].holdings[].ticker | string | yes | Resolved ticker via the local `cusip_mappings` table. Null when the CUSIP is unmapped (private securities, OTC, very-recently-issued). |
| data[].holdings[].security_name | string | yes | Canonical security name from `cusip_mappings`. |
| data[].holdings[].security_type | string | yes | Security type (e.g. `Common Stock`, `Preferred Stock`, `Warrant`, `Option`, `ADR`). |
Sample response
- "query":
- "cik": "0001067983"
- "formType": "13-F"
- "start_date": null
- "end_date": null
- "result": 1
- "data":
Errors
| Status | Label | Description |
|---|---|---|
| 200 | OK | Request succeeded. |
| 400 | Bad Request | Invalid query, body, or path parameter. |
| 401 | Unauthorized | Missing or invalid Authorization header / api_Token. |
| 402 | Payment Required | Insufficient token balance for this call. Top up |
| 429 | Too Many Requests | Rate limit exceeded for your tier (see /pricing for tier limits). Tier limits |
| 500 | Server Error | Unexpected server-side failure. Retry with backoff; report if persistent. |
Code samples
curl "https://api.finradar.ai/api/v1/scrapping/form-13f?api_Token=YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Generate an API key in /account/credentials to run live queries (literal YOUR_API_KEY placeholder shown until then).