| name | skatturinn |
| description | Iceland Tax Authority — annual reports (ársreikningar), company registry, ownership chain mapping by kennitala. |
Skatturinn (Iceland Tax Authority)
Company registry and annual reports (ársreikningar) from the Icelandic tax authority.
Overview
Skatturinn operates the Company Registry (Fyrirtækjaskrá) and Annual Reports Registry (Ársreikningaskrá). Annual reports are free of charge since January 1, 2021. Downloading goes through a server-side shopping cart, but no browser is required — the cart is cookie/viewstate state that httpx handles directly. See "Access Method" below.
Use case: Map company ownership chains by extracting beneficial owners from annual reports, then recursively looking up parent company reports.
URLs
| Resource | URL Pattern |
|---|
| Company lookup | https://www.skatturinn.is/fyrirtaekjaskra/leit/kennitala/{kennitala} |
| Search by name | https://www.skatturinn.is/fyrirtaekjaskra/leit?nafn={company_name} |
| Search page | https://www.skatturinn.is/fyrirtaekjaskra/leit |
| Annual reports info | https://www.skatturinn.is/fyrirtaekjaskra/arsreikningaskra/ |
| API Portal | https://api.skatturinn.is/ (requires registration, limited endpoints) |
Finding a Company's Kennitala
To find a company's kennitala by name, use WebFetch on the search URL:
https://www.skatturinn.is/fyrirtaekjaskra/leit?nafn={company_name}
Example: ?nafn=dansport returns the company page with kennitala 4807032350.
This is more reliable than Google searches. The page shows matching companies with their kennitala prominently displayed.
Data Available
Company Lookup Page
Each company page at /fyrirtaekjaskra/leit/kennitala/{kt} shows:
- Basic info: Name, kennitala, address, registration date, legal form
- Management: Directors, beneficial owners with ownership percentages
- Activity: ÍSAT codes (business classification)
- Annual reports table: List of submitted reports with:
- Operating year (Rek. ár)
- Submission date (Skiladagsetning)
- Report number (Nr. ársreiknings)
- Report type (Tegund ársreiknings)
Annual Report PDFs
Reports contain:
- Balance sheet, income statement, cash flow
- Beneficial ownership (Raunverulegir eigendur): Name, kennitala, ownership %
- Shareholders (Hluthafar): For smaller companies
- Notes on related party transactions
Access Method: plain HTTP (httpx) — no browser
No public API exists for downloading annual reports; the site drives a
server-side shopping cart. But it does not need a browser. scripts/skatturinn.py
imports no browser library at all — the whole flow, download included, is httpx
plus ASP.NET viewstate handling:
GET /fyrirtaekjaskra/leit/kennitala/{kt} -> scrape company + report rows
GET addToCart?itemid=…&typeid=… -> cart id (kid)
GET cart page -> extract __VIEWSTATE
POST cart page -> ZIP/PDF bytes
The cart is session state in cookies, not JavaScript. httpx.AsyncClient keeps
the cookie jar across those calls, which is all it ever needed.
Setup
uv sync
That is the whole setup. Do not install Chromium for this skill — earlier
versions of this file told you to, and it was wrong for long enough to mislead
both a human and an agent into planning browser-only monitoring.
tests/health/test_skatturinn.py is a plain HTTP probe for the same reason.
Page Structure (Verified)
Beneficial Owners - in .collapsebox elements:
<div class="collapsebox">
<span><h4>Viktor Ólason</h4></span>
<div class="tablewrap">
<table class="annualTable">
<thead>
<tr><th>Fæðingarár/mán</th><th>Búsetuland</th><th>Ríkisfang</th><th>Eignarhlutur</th><th>Tegund eignahalds</th></tr>
</thead>
<tbody>
<tr><td>1964-JÚNÍ</td><td>Ísland</td><td>Ísland</td><td>100%</td><td>Beint eignarhald</td></tr>
</tbody>
</table>
</div>
</div>
Annual Reports - table with td[data-itemid]:
<td data-itemid="808877" data-typeid="1">Ársreikningur<a href="#" class="tocart">Kaupa</a></td>
Report Type IDs:
| typeid | Type | Download |
|---|
| 1 | Ársreikningur (PDF) | Works |
| 4 | Rafrænn ársreikningur (XBRL?) | Different flow, may fail |
Some years have typeid=4 instead of 1. The current script only handles typeid=1 reliably.
Download Flow (Verified)
-
Add to cart via API:
GET /da/CartService/addToCart?itemid={itemid}&typeid={typeid}
Returns: {"addCartItemResult": true, "shoppingCartUrl": "https://vefur.rsk.is/Vefverslun/Default.aspx?kid=XXXX"}
-
Navigate to cart URL from response
-
Click "Áfram" button to proceed
-
Download triggers - clicking download button returns PDF
CLI Usage
uv run python scripts/skatturinn.py info 5012043070
uv run python scripts/skatturinn.py download 5012043070 --year 2024
uv run python scripts/skatturinn.py download 5012043070
uv run python scripts/skatturinn.py chain 5012043070 --depth 3
Anti-Bot Measures
Observed behavior:
- Session cookies required - JSESSIONID must persist across requests
- Rate limiting - 3 second delay recommended between requests
- Cross-domain flow - Cart redirects from skatturinn.is to vefur.rsk.is
PDF Extraction
Report Types
- Hnappurinn (Micro-company) - Simplified 4-page format without ownership section. Only financial statements.
- Full ársreikningur - Complete reports with ownership tables, auditor statements, detailed notes.
For ownership chain mapping, the web page scraping is more reliable since it shows current beneficial owners directly. PDF extraction is useful for historical ownership or additional shareholder detail in full reports.
Extract Command
uv run python scripts/skatturinn.py extract /path/to/report.pdf
The script looks for:
- Kennitala patterns:
\d{6}-?\d{4}
- Ownership percentages:
\d+%
- Section keywords: "eigend", "hluthaf", "eignarhald"
Ownership Chain Mapping
The main use case: follow ownership through multiple levels.
async def map_ownership_chain(
root_kennitala: str,
max_depth: int = 5,
visited: set[str] | None = None
) -> dict:
"""
Recursively map ownership chain starting from a company.
Returns nested structure:
{
"kennitala": "5012043070",
"name": "Example ehf.",
"owners": [
{
"kennitala": "1234567890",
"name": "Parent Company hf.",
"ownership_pct": 100.0,
"type": "company",
"owners": [...] # Recursive
},
{
"kennitala": "0101801234",
"name": "Jón Jónsson",
"ownership_pct": 50.0,
"type": "person" # No recursion for individuals
}
]
}
"""
if visited is None:
visited = set()
if root_kennitala in visited or max_depth <= 0:
return {"kennitala": root_kennitala, "circular_ref": True}
visited.add(root_kennitala)
info = await get_company_info(root_kennitala)
result = {
"kennitala": root_kennitala,
"name": info["name"],
"owners": []
}
for owner in info["beneficial_owners"]:
owner_kt = owner["kennitala"]
is_company = owner_kt[0] in "4567"
owner_data = {
"kennitala": owner_kt,
"name": owner["name"],
"ownership_pct": owner["ownership_pct"],
"type": "company" if is_company else "person"
}
if is_company:
owner_data["owners"] = (await map_ownership_chain(
owner_kt, max_depth - 1, visited
)).get("owners", [])
result["owners"].append(owner_data)
return result
Kennitala Format
Icelandic identification numbers:
| Type | Format | First digit | Example |
|---|
| Person | DDMMYY-NNNN | 0-3 (day) | 0101801234 (Jan 1, 1980) |
| Company | DDMMYY-NNNN | 4-7 | 5012043070 (Dec 10, 2004) |
The first 6 digits encode the registration date. Century determined by 9th digit:
- 8 = 1800s, 9 = 1900s, 0 = 2000s
Data Caveats
-
PDF variability: Report formats vary by year and preparer (accountant). Some are structured, some are scanned images.
-
Ownership on page vs PDF: The company lookup page shows current beneficial owners. The annual report PDF shows ownership as of fiscal year end - these may differ.
-
Holding structures: Beneficial owners may be foreign entities without Icelandic kennitala, making chain tracing incomplete.
-
Rate limits: Unknown but assume conservative limits. Add 2-5 second delays between requests.
-
Terms of service: No explicit prohibition on automated access, but bulk scraping may trigger blocks. Consider contacting fyrirtaekjaskra@skatturinn.is for data access agreements.
-
Session cookies: The shopping cart requires maintaining session state. Reuse one httpx.AsyncClient (and therefore one cookie jar) across addToCart → cart → download; a fresh client between those steps loses the cart.
Evidence Integration
Store extracted data in /data/processed/skatturinn/:
/data/
/raw/skatturinn/
/{kennitala}_{year}.pdf # Original PDFs
/processed/skatturinn/
/companies.csv # Company metadata
/ownership.csv # Ownership relationships
/ownership_chains.json # Full chain mapping
SQL queries in /evidence-reports/sources/skatturinn/:
SELECT
parent_kt,
child_kt,
ownership_pct,
depth
FROM read_csv('../data/processed/skatturinn/ownership.csv')
Quick Commands
uv run python scripts/skatturinn.py download --kennitala 5012043070 --year 2023
uv run python scripts/skatturinn.py chain --kennitala 5012043070 --depth 3
uv run python scripts/skatturinn.py bulk --input companies.txt --year 2023
Related Skills