Alþingi — Parliament XML

SkillMedia

Alþingi XML — MPs, per-MP vote records, bills, committees, speeches, ministers, lobbying submissions. Use for Icelandic parliamentary analysis.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Alþingi — Parliament XML skill

What this skill tells your AI

The instructions your AI receives, as published by jokull/icelandic-data in .agents/skills/althingi/SKILL.md and read by ahel’s review.

Open XML feeds from the Alþingi database: every MP since 1875, per-MP roll-call votes, the parliamentary matter catalogue, committee membership, speeches, ministerial appointments and consultation submissions.

API

Base URL: https://www.althingi.is/altext/xml/

No authentication, no rate limit published. Plain GET, no query language — each endpoint is a fixed path with query-string filters. Responses are text/xml; charset=utf-8.

Send a User-Agent. The site returns 403 Forbidden to httpx's default UA. Any identifying string is accepted — sending none, or a default library UA, is the failure mode. curl works out of the box, so this bites only when moving from a shell probe to code.

Responses are served through Cloudflare and come back cf-cache-status: HIT with an age of up to ~10 minutes. Combined with the daily refresh, treat anything you read as up to a day old.

Data refreshes once per day ("Gögnin uppfærast að öllu jöfnu einu sinni á sólarhring"), so there is nothing to gain from polling faster.

There is no schema

Alþingi states outright: "Ekki er til xml-skema fyrir gögnin, nema Alþingistíðindi" and "Framsetningin á gögnunum geta tekið breytingum án fyrirvara" — no XSD except for Alþingistíðindi, and the shape may change without notice.

In practice there is no schema at all. The two XSDs the index page links for the record proper — http://skema.althingi.is/skema/althingi_{gerdabok,raedur}.xsd — are dead: skema.althingi.is returns no DNS answer (checked 2026-08-15, while www.althingi.is resolves normally). Do not plan on validating against them.

So everything here is shape-by-observation. That is what the health probe guards, and it is why it asserts Icelandic element names rather than values.

Element names are Icelandic

Tags are <þingmaður>, <atkvæðagreiðsla>, <þingflokkur>, <kjördæmi> — non-ASCII, which is legal XML but unusual. Both lxml and stdlib xml.etree.ElementTree handle it; this repo uses the stdlib parser, so no new dependency. Parse from bytes (resp.content), never resp.text — the documents carry their own encoding declaration and a str input trips ValueError: Unicode strings with encoding declaration are not supported.

Common parameters

ParameterApplies toExampleNotes
lthingmost list endpoints?lthing=156Parliament (löggjafarþing) number
dagurrosters, votes, speeches?dagur=14.2.2013 or ?dagur=20190916Two date formats in the wildD.M.YYYY for rosters, YYYYMMDD for votes/speeches
dagarvotes, speeches?dagar=100Trailing window in days
malnrmatter detail?lthing=156&malnr=1Only unique within a málsflokkur — see caveat 3
nrper-person detail?nr=1547Person id, stable across parliaments
nnefndcommittee members?lthing=156&nnefnd=201Committee id

Endpoints

Core — what scripts/althingi.py fetches

EndpointRoot elementPurpose
loggjafarthing/löggjafarþingEvery parliament 1..N with dates and per-þing index links
loggjafarthing/yfirstandandi/löggjafarþingThe current parliament — resolve this at runtime, never hardcode
thingmenn/?lthing=NþingmannalistiEveryone who sat during þing N (members and substitutes)
thingmenn/thingmadur/thingseta/?nr=NþingmaðurParty + constituency + seat, per parliament. The only route to party affiliation
atkvaedagreidslur/?lthing=NatkvæðagreiðslurAll vote events of a parliament
atkvaedagreidslur/atkvaedagreidsla/?numer=NatkvæðagreiðslaOne vote with the per-MP ballot (<atkvæðaskrá>)
thingmalalisti/?lthing=NmálaskráAll matters (bills, resolutions, questions) of a parliament
nefndir/nefndarmenn/?lthing=NnefndarmennCommittee membership with start/end dates
thingfundir/?lthing=NþingfundirSittings: number, title, start/end timestamps
raedulisti/?lthing=NræðulistiSpeech metadata — speaker, times, links. Not the text

Also available — documented, not yet scripted

EndpointRoot elementWhat it holds
thingmenn/thingmadur/?nr=NþingmaðurOne MP: name, birth date, links
thingmalalisti/thingmal/?lthing=N&malnr=MþingmálA-matter detail: sponsors, stages, documents
thingmalalisti/bmal/?lthing=N&malnr=MbmálB-matter detail — a separate route, see caveat 3
nefndir/?lthing=NnefndirCommittees active in þing N
thingmenn/thingmadur/hagsmunir/?nr=NþingmaðurDeclarations of interest — an MP's directorships, shareholdings, paid roles. Joins to skatturinn ownership data by company name
erindi/?lthing=NerindaskráConsultation submissions to committees — the lobbying trail. ~800 KB per parliament
erindi/sendandi/?lthing=NsendendurWho submitted, aggregated by sender
thingmenn/thingmadur/lifshlaup/?nr=NþingmaðurBiography — education, career, offices
thingmenn/thingmadur/nefndaseta/?nr=NþingmaðurOne MP's committee history
thingskjol/?lthing=NþingskjölParliamentary documents index
thingskjol/thingskjal/?lthing=N&skjalnr=NþingskjalOne document
samantektir/?lthing=NsamantektirPlain-language summaries of matters
samantektir/samantekt/?lthing=N&malnr=MsamantektOne summary (often empty — 87 bytes)
efnisflokkar/efnisflokkarSubject taxonomy, two levels (yfirflokkurefnisflokkur)
efnisflokkar/efnisflokkur/?lthing=N&efnisflokkur=KefnisflokkarMatters in a subject category
nefndarfundir/nefndarfundirCommittee meetings. Trailing slash required — without it, 301 to HTML
dagskra/thingfundur/?lthing=N&fundur=MdagskráþingfundarOrder paper for one sitting
forsetar/?lthing=NforsetalistiSpeaker and deputy speakers
framsogumenn/?lthing=NframsögumannaskráCommittee rapporteurs per matter
thingflokkar/?lthing=NþingflokkarParliamentary groups with abbreviations
thingflokksformenn/?lthing=NþingflokksformennGroup chairs
kjordaemi/?lthing=NkjördæminConstituencies
radherrar/?dagur=D.M.YYYYráðherralistiMinisters on a given date
radherrar/radherraseta/?nr=NeinstaklingurOne person's ministerial terms
radherraembaetti/ráðherrarMinisterial offices over time
saetaskipan/?timi=ISOsætaskipunChamber seating. Seat numbers only — no party

Historical depth

Coverage starts at a different parliament per dataset — this is the first thing to check before any long-run series:

DatasetFromRoughly
MPs (þingmenn)þing 11875
Matters, documents, speechesþing 201907
Committeesþing 741954
Submissions (erindi)þing 1111988

Request examples

# Which parliament is sitting right now
curl -s "https://www.althingi.is/altext/xml/loggjafarthing/yfirstandandi/"

# Everyone who sat in þing 156
curl -s "https://www.althingi.is/altext/xml/thingmenn/?lthing=156"

# One MP's party and constituency, per parliament
curl -s "https://www.althingi.is/altext/xml/thingmenn/thingmadur/thingseta/?nr=1261"

# A single vote, with every MP's ballot
curl -s "https://www.althingi.is/altext/xml/atkvaedagreidslur/atkvaedagreidsla/?numer=67566"

# Votes on one matter / on one day / in the last 100 days
curl -s "https://www.althingi.is/altext/xml/atkvaedagreidslur/?lthing=150&malnr=1"
curl -s "https://www.althingi.is/altext/xml/atkvaedagreidslur/?dagur=20190916"
curl -s "https://www.althingi.is/altext/xml/atkvaedagreidslur/?dagar=100"

Schema

Vote event — atkvaedagreidslur/?lthing=N

<atkvæðagreiðsla málsnúmer='104' þingnúmer='156' málsflokkur='A' atkvæðagreiðslunúmer='67566'>
  <mál málsnúmer='104' þingnúmer='156' málsflokkur='A'>
    <málsheiti>ráðstöfun útvarpsgjalds</málsheiti>
  </mál>
  <tími>2025-02-18T14:09:52</tími>
  <fundur>7</fundur>
  <tegund tegund='as'>Of skammt var liðið frá útbýtingu --- Afbrigði</tegund>
  <samantekt>
    <aðferð>atkvæðagreiðslukerfi</aðferð>
    <já><fjöldi>44</fjöldi></já>
    <nei><fjöldi>0</fjöldi></nei>
    <greiðirekkiatkvæði><fjöldi>0</fjöldi></greiðirekkiatkvæði>
    <afgreiðsla>samþykkt</afgreiðsla>
  </samantekt>
  <nánar><xml>.../atkvaedagreidsla/?numer=67566</xml></nánar>
</atkvæðagreiðsla>
FieldXMLTypeExample
atkvgr_nr@atkvæðagreiðslunúmerINT67566 — globally unique, the join key
thing@þingnúmerINT156
malsnumer@málsnúmerINT104
malsflokkur@málsflokkurSTRA or B
malsheitimál/málsheitiSTRráðstöfun útvarpsgjalds
timitímiDATETIME2025-02-18T14:09:52 (ISO)
fundurfundurINT7 — sitting number
tegundtegundSTRWhat was voted on
tegund_koditegund/@tegundSTRas, v2, n2
adferdsamantekt/aðferðSTRSee vote-method table
ja / nei / greidir_ekkisamantekt/{já,nei,greiðirekkiatkvæði}/fjöldiINTNull when no ballot was taken
afgreidslasamantekt/afgreiðslaSTRsamþykkt / fellt

Per-MP ballot — atkvaedagreidsla/?numer=N

<atkvæðaskrá>
  <þingmaður id='1004'><nafn>Arna Lára Jónsdóttir</nafn><atkvæði>já</atkvæði></þingmaður>
  <þingmaður id='1510'><nafn>Alma D. Möller</nafn><atkvæði>fjarverandi</atkvæði></þingmaður>
</atkvæðaskrá>

<atkvæði> values, with Alþingi's own gloss from the XML comments:

Valuen (þing 156)Meaning
12,258Yes
nei1,676No
greiðir ekki atkvæði1,324Abstain — present in the chamber and pressed the abstain button
fjarverandi3,160Absent, not notified — pressed no button
boðaði fjarvist482Absent, notified — illness, or on parliamentary business

The abstain string is spaced here and unspaced in the summary block. The <samantekt>/<niðurstaða> count element is <greiðirekkiatkvæði> (one word); the <atkvæði> value inside <atkvæðaskrá> is greiðir ekki atkvæði (three words). Matching the element spelling against ballot values silently returns nothing — and because plenty of votes are unanimous, a spot check can easily miss it.

The distinction between the last two matters: boðaði fjarvist is an excused absence, fjarverandi is not. Collapsing them loses the signal.

Vote methods — aðferð

Observed across þing 156 (598 vote events):

aðferðCountCarries <atkvæðaskrá>?
atkvæðagreiðslukerfi299yes — electronic voting
yfirlýsing forseta/mál gengur297no — Speaker's declaration, no ballot
nafnakall1yes — roll call
handaupprétting1no — show of hands, count only

MP roster — thingmenn/?lthing=N

FieldXMLExample
thingmadur_id@id1547 — stable person id
nafnnafnAðalsteinn Leifsson
faedingardagurfæðingardagur1967-06-17 (ISO)
skammstofunskammstöfunALeif

Parliamentary service — thingseta/?nr=N

This is where party and constituency live. One <þingseta> per parliament, and more than one if the MP changed party or seat mid-þing.

FieldXMLExample
thingþing156
tegundtegundþingmaður, varamaður (substitute), or með varamann (seat-holder currently replaced by a substitute) — three values, not two
thingflokkur / thingflokkur_idþingflokkur + @idViðreisn / 45
kjordaemi / kjordaemi_idkjördæmi (CDATA) + @idReykjavíkurkjördæmi suður / 45
kjordaemanumerkjördæmanúmer7
thingsalssaetiþingsalssæti2
inn / uttímabil/{inn,út}21.05.2025 / 27.05.2025D.M.YYYY, not ISO

<út> is absent for a currently-serving MP.

Matters — thingmalalisti/?lthing=N

FieldXMLExample
malsnumer@málsnúmer1
thing@þingnúmer156
malsflokkur@málsflokkurA or B
malsheitimálsheitibreytt skipan ráðuneyta í Stjórnarráði Íslands
malstegundmálstegund/heitiTillaga til þingsályktunar
malstegund_kodimálstegund/@málstegunda, l, m, þi

Matter types on þing 156 — 716 matters, 504 A and 212 B:

málstegundn
Fyrirspurn (written question)266
óundirbúinn fyrirspurnatími (oral questions)202
Frumvarp til laga (bill)131
Tillaga til þingsályktunar (resolution)71
Skýrsla (report)23
sérstök umræða (special debate)10
Beiðni um skýrslu (report request)9
Álit (opinion)4

Committee membership — nefndir/nefndarmenn/?lthing=N

FieldXMLTypeExample
thingrequest lthingINT156
nefnd_idnefnd/@idINT201
nefndnefnd/heitiSTRallsherjar- og menntamálanefnd
thingmadur_idnefnd/nefndarmaður/@idINT1547
nafnnefnd/nefndarmaður/nafnSTRAðalsteinn Leifsson
stadanefnd/nefndarmaður/staðaSTRvaramaður
hofst / lauknefndasetahófst / nefndasetulaukDATE2025-02-04 / 2025-09-08; lauk is null while active

Sittings — thingfundir/?lthing=N

FieldXMLTypeExample
thingrequest lthingINT156
fundurþingfundur/@númerINT1
fundarheitifundarheitiSTRSitting title
dagurhefst/dagur, falling back to fundursetturDATE2025-02-04
dagur_aaetladderivedBOOLWhether dagur came from the schedule
hefst_textihefst/textiSTRFree-text scheduling note, nullable
hefsthefst/dagurtímiDATETIMEScheduled start, nullable
fundursettur / fundarslitfundursettur / fuslitDATETIMEActual opening and close

Speeches — raedulisti/?lthing=N

FieldXMLTypeExample
thingrequest lthingINT156
thingmadur_idræðumaður/@idINTSpeaker/person id when present
nafnræðumaður/nafnSTRSpeaker name
dagurdagurDATE2025-02-18
fundurfundurINTSitting number
fundarheitifundarheitiSTRSitting title
hofst / laukræðahófst / ræðulaukDATETIMESpeech start and end
tegundtegundræðuSTRSpeech type
umraedaumræðaSTRDebate stage
malsflokkur / malsnumermál/{málsflokkur,málsnúmer}STR / INTMatter key, nullable
malsheitimál/málsheitiSTRMatter title, nullable

Script usage

uv run python scripts/althingi.py list                        # every parliament, current one flagged
uv run python scripts/althingi.py list --datasets             # what fetch can pull

uv run python scripts/althingi.py fetch --dataset members     # roster + party + constituency
uv run python scripts/althingi.py fetch --dataset votes       # vote events + per-MP ballots
uv run python scripts/althingi.py fetch --dataset bills
uv run python scripts/althingi.py fetch --dataset committees
uv run python scripts/althingi.py fetch --dataset sittings
uv run python scripts/althingi.py fetch --dataset speeches
uv run python scripts/althingi.py fetch --dataset all

uv run python scripts/althingi.py fetch --dataset votes --thing 155      # a past parliament
uv run python scripts/althingi.py fetch --dataset members --thing 150-156
uv run python scripts/althingi.py fetch --dataset votes --force          # ignore the raw cache

--thing defaults to the parliament returned by loggjafarthing/yfirstandandi/.

Data files

PathFormatDescription
data/raw/althingi/*.xmlXMLEvery response, cached verbatim. Closed þing are cached permanently; current feeds refresh after 24h. --force always re-downloads
data/processed/althingi_members.parquetParquetOne row per (MP, parliament, party spell)
data/processed/althingi_votes.parquetParquetOne row per vote event
data/processed/althingi_ballots.parquetParquetOne row per (vote, MP) — the per-MP records
data/processed/althingi_bills.parquetParquetOne row per matter in the catalogue; no stage/document detail
data/processed/althingi_committees.parquetParquetOne row per (committee, MP, spell)
data/processed/althingi_sittings.parquetParquetOne row per sitting. dagur is the scheduled date, or the opening date when none was scheduled; dagur_aaetlad flags which
data/processed/althingi_speeches.parquetParquetOne row per speech (metadata only)

Column names are ASCII snake_case transliterations of the Icelandic tags — the mapping is in the schema tables above. Values keep their Icelandic characters.

Caveats

  1. Half the "votes" are not votes. atkvaedagreidslur/?lthing=N returned 598 entries for þing 156, but only 301 involved a ballot; the other 297 are yfirlýsing forseta/mál gengur — the Speaker declaring a matter advanced unopposed. Counting rows to get "votes this session" roughly doubles the real figure. Filter on afgreidsla / vote counts being present.

  2. Do not filter per-MP ballots on aðferð == 'atkvæðagreiðslukerfi'. nafnakall (roll call) also carries a full <atkvæðaskrá> — 63 MPs on the one þing-156 instance. It is rare, and it is exactly the kind of vote that gets called on contentious matters, so dropping it biases the sample in the worst possible direction. handaupprétting (show of hands) carries counts but no per-MP record. The script keys off the presence of <atkvæðaskrá>, not the method name.

  3. málsnúmer is only unique within a málsflokkur. A- and B-matters number independently and have separate detail routes. On þing 156, thingmal/?malnr=11 is "sameiningar háskóla" (a question) while bmal/?malnr=11 is "forseti Íslands setur þingið" (the state opening) — different matters, same number. The natural key is (þingnúmer, málsflokkur, málsnúmer). Joining on málsnúmer alone silently mixes them.

  4. Dates come in three formats, and Alþingi intends to change them. D.M.YYYY (01.07.1875) in löggjafarþing, þingseta, þingfundir; ISO YYYY-MM-DD in fæðingardagur; ISO datetime in votes and speeches. The site's own To-Do list has "Breyta dagsetningum í ISO" pending, so the first form will migrate at some point without notice. Normalise on read and accept both.

  5. The sitting parliament has no <þinglok>. Every closed þing carries an end date; the current one carries only <þingsetning>. A parser that assumes the element is present breaks on the current þing specifically — the one you most want to query.

  6. Never hardcode the parliament number. Resolve it from loggjafarthing/yfirstandandi/. Þing 157 opened 2025-09-09.

  7. Sentinel rows with empty names. kjördæmi id=1 and þingflokkur id=26 have empty CDATA <heiti> and - as their abbreviation. They are "unknown/none" placeholders, not real constituencies or parties. Filter them out or they show up as a blank category in every grouping.

  8. <niðurstaða> nests inside <niðurstaða>. In the vote-detail document the outer element is the result block and the inner one is the verdict string (samþykkt). An unanchored XPath grabs whichever comes first — use niðurstaða/niðurstaða for the verdict. Note the list endpoint calls the same block <samantekt> and the verdict <afgreiðsla>: the two endpoints use different tag names for the same thing.

  9. The MP roster includes substitutes. thingmenn/?lthing=156 returns 105 people for a 63-seat parliament, because every varamaður who sat for even a week is in there. þingseta/tegund separates þingmaður from varamaður, and tímabil gives the spell. Head-counting the roster is not a seat count.

  10. One MP can have several <þingseta> entries for one þing — and the usual reason is not a party switch. Þing 156 yields 313 spells for 105 people, because the record is re-cut every time a substitute steps in: Alma D. Möller alone has six consecutive spells, same party, same constituency, differing only in tímabil. members is therefore one row per spell, not per MP. Deduplicate on (thingmadur_id, thing) before joining to votes, or every ballot gets multiplied.

    Spells can also start before the parliament convenes — þing 156 opened 2025-02-04, but spells run from 2024-11-30, the day after the election that produced it.

  11. Speeches are metadata only. raedulisti gives speaker, sitting, times and links to the text and audio — not the text itself. It is also large: 12.4 MB and 13,623 speeches for þing 156 alone.

    Speakers are not all MPs. <ræðumaður> carries role elements such as <forsetiÍslands>; the first speech of þing 156 is by Halla Tómasdóttir, President of Iceland, opening the session. An inner join from speeches to members on thingmadur_id therefore drops real speeches — use a left join and expect unmatched rows.

  12. nefndarfundir needs a trailing slash. Without it the server 301s to an HTML page, so a naive fetch parses HTML as XML and fails obscurely.

    Relatedly, not every sitting has a scheduled date. A sitting called relative to another one carries only free text — <hefst><texti>að loknum 37. fundi</texti></hefst>, "once the 37th concludes" — with no <dagur> and no <dagurtími>. That is 8 of 92 sittings on þing 156. The script falls back to the date part of <fundursettur> (when the sitting was actually opened) and sets dagur_aaetlad = false on those rows, so dagur is never null and the provenance stays visible.

  13. Parse bytes, not text. The documents carry an encoding declaration; handing a decoded str to an XML parser raises ValueError. Use resp.content.

  14. No schema, changes without notice. Alþingi says so explicitly, and the XSDs they link are on a host that no longer resolves. This is what tests/health/test_althingi.py watches — it asserts the Icelandic element names still exist, since a silent retag is the likeliest break.

  15. greiðir ekki atkvæði (value) vs greiðirekkiatkvæði (element). The same concept is spelled two ways in the same document family — see the ballot-value table above. This one is easy to get wrong and hard to notice.

Sources

Signals

GitHub stars
53
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
althingi
Source
github.com/jokull/icelandic-data