danlex provides access to Danish legislation published by Retsinformation, the official state legal information system. This vignette works through a single instrument in detail and then scales up to the corpus.
This vignette was pre-computed: the code was run against the live service when the package was built, so the results below are real but the examples do not call the API when the package is checked or installed.
Danish acts and regulations are cited by year and number — “bekendtgørelse nr. 763 af 1998”. That maps directly onto an identifier:
doc <- dlx_get_doc("lta", 1998, 763)
doc$title
#> [1] "Bekendtgørelse om indbetaling af Den Særlige Pensionsopsparing for medlemmer af arbejdsløshedskasser for lønmodtagere ved udbetaling af dagpenge m.v."
doc$document_type
#> [1] "Bekendtgørelse"
doc$ministry
#> [1] "Beskæftigelses- og Ligestillingsministeriet"The first argument is the collection. lta is
Lovtidende A, which carries both acts and regulations in a
single number space — so the instrument above is a
bekendtgørelse even though it sits in the same series as acts.
The type is never inferable from the identifier alone, which is why
document_type is always returned.
The other collections are ltb and ltc
(Lovtidende B and C, the latter carrying treaties),
mt (Ministerialtidende, discontinued in 2012),
retsinfo (administrative decisions), fob
(Ombudsman decisions) and ft (parliamentary documents).
A document that does not exist is a normal answer, not an error:
Retsinformation returns full text only for material published from
late September 2007 onward. Earlier documents carry metadata alone, and
status reports this:
The boundary is sharp. Act 1080 of 2007, announced on 14 September, has no text; act 1081, announced on 25 September, does:
dlx_get_doc("lta", 2007, 1080)$status
#> [1] "metadata_only"
dlx_get_doc("lta", 2007, 1081)$status
#> [1] "ok"This is a property of the source. Metadata for earlier material is
complete and reaches back to 1852 for Lovtidende A — and, in the
retsinfo collection, to 1665.
For a modern instrument, dlx_get_text() returns the
running text with its structural markers in place:
txt <- dlx_get_text("lta", 2025, 50)
txt$n_char
#> [1] 9601
cat(substr(txt$text, 1, 400))
#> I medfør af § 7 b, stk. 2, § 22, stk. 1, nr. 1, 3, 4, 5, 6 og 7, og stk. 3-4, § 23 og § 30 i lov om erhvervsakademiuddannelser og professionsbacheloruddannelser, jf. lovbekendtgørelse nr. 396 af 12. april 2024, fastsættes efter bemyndigelse i henhold til § 4, stk. 1, i bekendtgørelse nr. 1118 af 28. oktober 2024 om delegation af uddannelses- og forskningsministerens beføjelser til Uddannelses- ogDanish legal drafting is highly structured, and Retsinformation
preserves that structure in its XML. dlx_get_paragraphs()
returns one row per subsection, so provisions can be handled as data
rather than as text to be parsed:
p <- dlx_get_paragraphs("lta", 2025, 50)
nrow(p)
#> [1] 25
p[1:4, c("paragraf", "stk", "text")]
#> # A tibble: 4 × 3
#> paragraf stk text
#> <chr> <chr> <chr>
#> 1 § 1. <NA> Formålet med erhvervsakademiuddannelsen som maritim teknolog…
#> 2 § 1. Stk. 2. Den uddannede skal have viden, færdigheder og kompetencer (l…
#> 3 § 1. Stk. 3. Den uddannede, som har gennemført de maritime valgfag, skal …
#> 4 § 2. <NA> Uddannelsen giver den uddannede ret til at anvende titlen ma…Note that the first subsection of each section carries no marker:
Stk. 1. is implicit in Danish drafting practice and simply
absent from the source.
An amending instrument contains provisions that are not its own —
they are new text destined for another instrument. The
is_amendment column makes the distinction:
own <- dlx_get_paragraphs("lta", 2025, 50)
amd <- dlx_get_paragraphs("lta", 2025, 1)
table(own$is_amendment)
#>
#> FALSE
#> 25
table(amd$is_amendment)
#>
#> TRUE
#> 12The second instrument amends a regulation from 2018; every provision it contains belongs to that regulation, not to itself. Treating the two alike would badly distort any corpus-level analysis of what Danish law says.
Regulations record the provisions they were issued under, and
dlx_get_references() returns these as an edge table:
refs <- dlx_get_references("lta", 1998, 763)
refs[, c("ref_accn", "ref_date", "ref_title")]
#> # A tibble: 2 × 3
#> ref_accn ref_date ref_title
#> <chr> <date> <chr>
#> 1 A19990059229 1999-07-14 Bekendtgørelse af lov om arbejdsløshedsforsikring m.v.
#> 2 A19990066629 1999-08-19 Bekendtgørelse af lov om en aktiv arbejdsmarkedspolit…The ref_accn values are accession numbers, which
dlx_get_doc() accepts directly — so a citation network can
be traversed without building a lookup table first:
parent <- dlx_get_doc(accn = refs$ref_accn[1])
parent$title
#> [1] "Bekendtgørelse af lov om arbejdsløshedsforsikring m.v."
parent$document_type
#> [1] "Lovbekendtgørelse"One property deserves emphasis before anyone builds a network from this data. The referring instrument is from 1998, yet its references are dated 1999:
This is not an error. Retsinformation updates these links to point at the current consolidated version of the parent act, so they reflect the state of the law now rather than at the moment of enactment. An analysis that treats the edges as timestamped to the referring document’s date will be systematically wrong.
dlx_list_documents() retrieves the full index of
everything published through the service:
idx <- dlx_list_documents(progress = FALSE)
nrow(idx)
#> [1] 202924
table(idx$collection)
#>
#> fob ft lta ltb ltc mt retsinfo
#> 2957 41492 63218 45 4783 6438 83991The first call takes about a minute, because the index is published as a sitemap split across 21 pages whose ordering does not permit fetching a single year. The result is held for the rest of the session, so later calls are immediate.
Nothing is written to disk. To keep the index between sessions, save it:
The index carries identifiers and modification dates only. Note that
lastmod records when Retsinformation last revised its
record, which is unrelated to when the instrument was enacted
or repealed.
The index is the quickest way to see what is actually available:
lta <- subset(idx, collection == "lta" & !is.na(year))
range(lta$year)
#> [1] 1852 2026
mt <- subset(idx, collection == "mt" & !is.na(year))
max(mt$year)
#> [1] 2012Ministerialtidende ends in 2012 because it was discontinued.
Ombudsman decisions (fob) begin in 1980, and treaties
(ltc) drop off sharply after 2008. These are genuine
historical discontinuities rather than gaps in coverage, and an empty
result for a given year may simply mean nothing was published.
dlx_get_docs() takes a vector of identifiers. Here is
every treaty published in 2025:
treaties <- dlx_list_documents(year = 2025, collection = "ltc",
progress = FALSE)
docs <- dlx_get_docs(treaties$eli, progress = FALSE)
nrow(docs)
#> [1] 6
table(docs$status)
#>
#> ok
#> 6Failures are returned as rows with status = "error"
rather than raised as conditions, so a long run survives a dropped
connection:
Once retrieved, the metadata is ordinary data:
The index is refreshed monthly, so recent material may be missing
from it. dlx_get_changes() reads a separate feed covering
at least the last 60 days:
ch <- dlx_get_changes()
nrow(ch)
#> [1] 405
range(ch$updated)
#> [1] "2026-07-02" "2026-08-29"
table(ch$published_in)
#>
#> Lovtidende A Lovtidende C Retsinformation
#> 101 2 302The feed itself records only the publication channel, not the
collection. danlex derives collection from the identifier,
which makes it possible to separate legislation from administrative
decisions:
recent_acts <- dlx_get_changes(collection = "lta", reason = "NewDocument")
nrow(recent_acts)
#> [1] 83
head(recent_acts$title, 3)
#> [1] "Bekendtgørelse om Ledningsejerregistret"
#> [2] "Bekendtgørelse om landsplandirektiv for to arealer til højspændingsstationer i hhv. Køge Kommune og Stevns Kommune"
#> [3] "Bekendtgørelse om kriterier for vurdering af kommunale projekter vedrørende vandløbsrestaurering"Because the feed is a static file with no query interface, these filters apply after retrieval. Asking for a date earlier than the feed reaches will return a truncated result and warn.
The whole corpus is around 200,000 documents, of which roughly 74,000 are legislation in the strict sense. Full text is available from late 2007 onward, structured down to the subsection, with maintained cross-references throughout. That combination supports work that is awkward against most national legal sources: provision-level text analysis, citation network construction, and long-run measurement of legislative output.
danlex is part of lexverse, a family of R packages for legal and regulatory data alongside eurlex, finlex and swelex.
Retsinformation’s data is provided by Civilstyrelsen. Consult the terms at https://www.retsinformation.dk/api before redistributing it or using it commercially.