EU law · 24 official languagesArticle-level JSON · typed citation graphMCP server · Claude, Cursor, VS CodeSDKs · Python, TypeScriptFree plan · 500 credits to start
Brussels · CET
Vol. II·Section G — Developer Guides
EUR-Lex · CELEX · ELI · Cellar

§ Guide — For developers

EUR-Lex URLs and the EUR-Lex web service, explained for developers.

A EUR-Lex document is addressed by its CELEX number: legal-content/EN/TXT/?uri=CELEX:32016R0679 is the GDPR in English. Everything else in the link — TXT or ALL, HTML or PDF, a qid — either picks a view of that document or is not needed at all.

Below: what each part of a document link and a search link means, how CELEX numbers and ELIs are built, and the official machine routes — the EUR-Lex web service and the Publications Office’s Cellar — with what each is good and bad at.

§ 01 — Document links

Anatomy of a legal-content URL.

The document is the CELEX in uri=; the rest is presentation

https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32016R0679
https://eur-lex.europa.eu/legal-content/EN/ALL/?uri=CELEX:32016R0679
https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679
https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32016R0679
https://eur-lex.europa.eu/legal-content/EN/TXT/XML/?uri=CELEX:32016R0679
PartWhat it means
https://eur-lex.europa.eu/legal-content/The document pages of EUR-Lex.
ENThe language of the page: any of the 24 official EU languages, as an upper-case two-letter code (EN, FR, DE, …).
TXT/The document’s text page on EUR-Lex.
ALL/The document’s information page: title, dates, author, classification and relations to other acts.
TXT/HTML/ · TXT/PDF/ · TXT/XML/The text alone, as HTML, PDF or XML.
?uri=CELEX:32016R0679The document itself, by its CELEX number. Browsers often percent-encode the colon (CELEX%3A32016R0679); it is the same address.
&qid=…Not part of the address. Links copied from EUR-Lex often carry it, for example on pages opened from a search; drop it and the URL still names the same document.

EUR-Lex also links legislation by its ELI, for example https://eur-lex.europa.eu/eli/reg/2024/1689/oj for the AI Act (§ 03). To store a reference, store the CELEX number; you can rebuild every link above from it.

§ 02 — CELEX numbers

Sector, year, type, number.

Read left to right: 3 · 2016 · R · 0679

3  2016  R  0679
│  │     │  └─ number, padded to four digits
│  │     └──── type: R regulation, L directive, D decision
│  └────────── year
└───────────── sector: 3 = legislation

32016R0679 is Regulation (EU) 2016/679, the GDPR. In case law (sector 6) the year is the year the case was brought and the letters name the court and the kind of document: 62018CJ0311 is the Court of Justice judgment in case C-311/18, and an Advocate General’s opinion in the same case would read 62018CC0311.

Main sectorsWhatExample
0Consolidated versions02016R0679-20160504
1Treaties—
2International agreements—
3Legislation32016R0679 (GDPR), 32024R1689 (AI Act)
4Complementary legislation—
5Preparatory acts—
6Case law62018CJ0311 (Schrems II, C-311/18)
9Parliamentary questions—
LettersTypeIn
RRegulationsector 3
LDirectivesector 3
DDecisionsector 3
CJCourt of Justice judgmentsector 6
CCAdvocate General’s opinionsector 6
COCourt of Justice ordersector 6
TJ · TOGeneral Court judgment · ordersector 6

Suffixes

  • Consolidated versions — sector 0, the base act’s number and the consolidation date: 02016R0679-20160504. They are the Publications Office’s documentation tool; the authentic text is the one published in the Official Journal.
  • Corrigenda — the act’s number with R(01), R(02)…: 32008R1272R(01).
  • Sequence qualifiers — a number in brackets, as in 32019D0003(01). Brackets must be percent-encoded (%28, %29) when the number goes into a Cellar URL.
§ 03 — ELI

The European Legislation Identifier.

A URI per act; usually maps straight to the CELEX number for regulations, directives and decisions

http://data.europa.eu/eli/reg/2024/1689/oj   →  32024R1689   (regulation: R)
http://data.europa.eu/eli/reg/2016/679/oj    →  32016R0679
eli/dir/{year}/{number}                      →  3{year}L{number, 4 digits}   (directive: L)
eli/dec/{year}/{number}                      →  3{year}D{number, 4 digits}   (decision: D)

For regulations, directives and decisions the mapping is usually mechanical: sector 3, the year, the type letter and the number padded to four digits. Note the letter for a directive is L, not D. It is not always so: some acts carry a CELEX with a sequence qualifier that the ELI doesn’t show — eli/dec/2019/166/oj is CELEX 32019D0003(01), not 32019D0166. When it matters, and for other ELI types, look it up — Cellar SPARQL returns a document’s ELI as cdm:resource_legal_eli (§ 05).

§ 04 — Search links

The parameters of a search URL.

search.html?type=advanced&…

https://eur-lex.europa.eu/search.html?type=advanced&lang=en
  &DTS_DOM=EU_LAW&SUBDOM_INIT=EU_LAW&DTS_SUBDOM=LEGISLATION
  &textScope0=ti-te&andText0=artificial+intelligence
  &DD_YEAR=2024&FM_CODED=REG
ParameterWhat it does
type=advancedThe advanced search form.
langInterface language, lower case (en).
DTS_DOMThe collection: EU_LAW for EU law, ALL for every collection.
SUBDOM_INITSent with DTS_DOM, set to the same collection (ALL_ALL when searching everything).
DTS_SUBDOMA part of the collection: LEGISLATION, CONSLEG (consolidated texts), TREATIES, EU_CASE_LAW, PRE_ACTS (preparatory acts), INTER_AGREE, PAR_QUESTION, LEGAL_PROCEDURE, or ALL_ALL.
textScope0 + andText0Search text (andText0) and where to look for it (textScope0): ti = title, te = text, ti-te = both.
DD_YEAR · DD_MONTH · DD_DAYDate of the document; the …_TO variants (DD_YEAR_TO, DD_MONTH_TO, DD_DAY_TO) close a range.
FM_CODEDDocument form: REG, DIR, DEC, JUDG, ORDER, OPIN, COMMUNIC, REG_IMPL, DEC_IMPL, …
AU_CODEDAuthor: COM (Commission), CONSIL (Council), EP (Parliament), CJ (Court of Justice), …
PROC_TYPProcedure type, for example OLP (ordinary legislative procedure).

What we learned the hard way

  • Only the first FM_CODED counts: FM_CODED=REG&FM_CODED=DIR returns regulations only. Run one search per form.
  • Only the first DTS_SUBDOM counts too.
  • A form filter with a full-year day range (1 January to 31 December, as DD_DAY/DD_MONTH) returns nothing; with DD_YEAR alone it works.
  • AU_CODED has a working value for the Court of Justice (CJ) but none for the General Court: filter its documents by CELEX instead (sector 6, letter T).
§ 05 — Official access

The web service, Cellar, and the website.

What each official route gives you, and what it costs you to use

RouteGives youAccessWatch out for
EUR-Lex web service (SOAP)Search: an expert query in, matching documents’ metadata out (title, date, form, author, languages, links), up to 100 per page. Full-text search included (TE ~).Register with an EU Login account; registration is reviewed before access is granted. A daily call quota per account.SOAP 1.2 with a WS-Security password token. Calls made back to back fault or return zero hits: space them out. Returns no parsed text.
Cellar SPARQLMetadata and relations for any document: dates, ELI, ECLI, type, author, Official Journal reference, amendments, consolidated versions.Open: no registration, no key.No full-text search of document content. No service level: long queries are cut off at about 60 seconds.
Cellar content negotiation (REST)The document itself: XHTML text, Formex XML, PDF, or the metadata notice, by CELEX number.Open: no registration, no key.Accept and a three-letter Accept-Language are required. You parse the XHTML or Formex yourself. Some older acts exist only as PDF scans.
eur-lex.europa.eu pagesThe pages people read: text, information page, search results.Open in a browser.Behind a web application firewall: plain HTTP clients get a JavaScript challenge (HTTP 202), not the page. Not an interface for programs.

The EUR-Lex web service (search)

A SOAP 1.2 service at https://eur-lex.europa.eu/EURLexWebService, authenticated with a WS-Security username token. The username is your EU Login id, not your email address. A request carries an expert query, a page number, a page size (at most 100) and a search language:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:sear="http://eur-lex.europa.eu/search">
  <soap:Header>
    <wsse:Security soap:mustUnderstand="true"
        xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken>
        <wsse:Username>your-eu-login-id</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">…</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <sear:searchRequest>
      <sear:expertQuery>TI ~ "artificial intelligence" AND FM_CODED = REG AND DD &gt;= 01/01/2024</sear:expertQuery>
      <sear:page>1</sear:page>
      <sear:pageSize>100</sear:pageSize>
      <sear:searchLanguage>en</sear:searchLanguage>
    </sear:searchRequest>
  </soap:Body>
</soap:Envelope>
Expert-query fieldMeaning
TI ~ "…" · TE ~ "…"Words in the title · in the text
DD >= 01/01/2024Date of the document, as dd/mm/yyyy (with <= for the end of a range)
FM_CODED = REGDocument form — the same codes as the search URL
AU_CODED = COMAuthor
DTS_SUBDOM = LEGISLATIONPart of the collection
  • Clauses combine with AND / OR and brackets, and several values of one field are an OR: (FM_CODED = REG OR FM_CODED = DIR) — one call, unlike the search URL.
  • DTS_DOM is a URL parameter, not an expert-query field: DTS_DOM = EU_LAW matches nothing. EU law is the default collection, so leave it out.
  • For a date of document use DD. DTA is a different field: DTA = 2026 with judgments returned 2 hits where the DD range for 2026 returned 599.
  • Space your calls out (we wait a second between calls): back-to-back calls fault with “The call must not be performed within the idle interval” — or answer with zero hits.

Cellar SPARQL (metadata)

Cellar is the Publications Office repository that feeds EUR-Lex. Its SPARQL endpoint, https://publications.europa.eu/webapi/rdf/sparql, answers anonymous POST requests; reuse, commercial included, is allowed under Decision 2011/833/EU with the source acknowledged. This query returns the AI Act’s date, Official Journal publication date and ELI:

curl https://publications.europa.eu/webapi/rdf/sparql \
  -H 'Accept: application/sparql-results+json' \
  --data-urlencode [email protected]

# q.rq
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?dateOfDocument ?ojPublished ?eli WHERE {
  ?work cdm:resource_legal_id_celex "32024R1689"^^xsd:string ;
        cdm:work_date_document ?dateOfDocument ;
        cdm:official-journal-act_date_publication ?ojPublished ;
        cdm:resource_legal_eli ?eli .
}
# → 2024-06-13, 2024-07-12, http://data.europa.eu/eli/reg/2024/1689/oj
  • Type the CELEX literal: "32024R1689"^^xsd:string. Untyped, the same query returns zero rows, without an error.
  • cdm:work_date_document (the act’s date) and cdm:official-journal-act_date_publication (its Official Journal date) are different dates — pick the one you mean.
  • Grouping across documents? Aggregate typed dates as MAX(STR(?date)): an aggregate over the typed value can return another group’s date.
  • Titles are searchable (bif:contains); document text is not — that is what the web service is for.

Cellar content negotiation (the document itself)

Every document has a URL by CELEX number under http://publications.europa.eu/resource/celex/; the format is chosen with the Accept header and the language with a three-letter Accept-Language (eng, deu, fra…):

# XHTML text (the markup EUR-Lex shows, article ids included)
curl -L -H 'Accept: application/xhtml+xml' -H 'Accept-Language: eng' \
  http://publications.europa.eu/resource/celex/32024R1689

# Formex 4 XML, as a zip
curl -L -H 'Accept: application/zip;mtype=fmx4' -H 'Accept-Language: eng' \
  http://publications.europa.eu/resource/celex/32016R0679 -o gdpr-fmx4.zip

# The metadata notice
curl -L -H 'Accept: application/xml;notice=branch' -H 'Accept-Language: eng' \
  http://publications.europa.eu/resource/celex/32016R0679
  • Without Accept-Language the request fails with 400. text/html is not a format Cellar serves documents in: ask for application/xhtml+xml.
  • Formex as application/xml;mtype=fmx4 fails; the zip always works.
  • Percent-encode brackets in a CELEX number (32013R0952R%2804%29); unencoded, the request 404s.
  • Not every document has every format. Many regulations from before 2005 exist only as scanned PDFs; in our checks EUR-Lex had no HTML text for them either.
§ 06 — The same, as JSON

Skip the parsing: LexAPI.

An independent REST API over the same sources — not an official EU service

LexAPI takes any of the identifiers above and returns the document as JSON — metadata, full text, and the articles, recitals and annexes as separate items. One API key in the x-api-key header; requests copied from the documentation.

# A pasted EUR-Lex link — qid and all; the CELEX is read from uri=
curl -X POST "https://lex-api.com/api/v1/documents/url" \
   -H "x-api-key: $LEX_KEY" \
   -H "Content-Type: application/json" \
   -d '{"url":"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32016R0679"}'

# Any identifier — CELEX, EUR-Lex URL, ELI or ECLI — to the CELEX and its four EUR-Lex URLs
curl -X POST "https://lex-api.com/api/v1/resolve" \
   -H "x-api-key: $LEX_KEY" \
   -H "Content-Type: application/json" \
   -d '{"identifier":"http://data.europa.eu/eli/reg/2024/1689/oj"}'

# The document by CELEX — or one article of it
curl -X POST "https://lex-api.com/api/v1/documentContent" \
   -H "x-api-key: $LEX_KEY" \
   -H "Content-Type: application/json" \
   -d '{"celexNumber":"32024R1689","articleId":"art_50","include":["metadata","articles"]}'

Costs: a document read is 5 credits, settled at 1 when it is served from the LexAPI corpus and 4 when it comes from Cellar; /resolve is 1. /documents/url reads the English text; /documentContent takes a language. The Free plan starts with 500 credits, then 150 a month, no card. Searching works the same way — POST /api/v1/search takes plain parameters (query, documentType, dateFrom…) instead of an expert query. By-URL reference →

§ 07 — FAQ

Asked &
answered.

Every request shape and response field is in the API documentation.

N° 01What does qid mean in a EUR-Lex URL?+
Links copied from EUR-Lex often carry a qid parameter, for example on pages opened from a search. It is not part of the document’s address: the document is the CELEX number in uri=. https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32016R0679 addresses the GDPR without any qid, and LexAPI’s URL endpoints read only the CELEX number, so a link with qid works the same.
N° 02What is the difference between TXT, ALL, HTML and PDF in a EUR-Lex link?+
They choose what EUR-Lex returns for the document named in uri=. legal-content/EN/TXT/ is the document’s text page, ALL/ its information page (title, dates, author, classification and relations to other acts), and TXT/HTML/, TXT/PDF/ and TXT/XML/ the text alone in that format. EN is the language: any of the 24 official EU languages, as an upper-case two-letter code.
N° 03How is a CELEX number structured?+
Sector, year, document type, number. In 32016R0679, the GDPR, 3 is the sector (legislation), 2016 the year, R the type (regulation) and 0679 the number. Directives use L and decisions D; case law is sector 6, where 62018CJ0311 is a Court of Justice judgment in case C-311/18. Consolidated versions are sector 0 with the consolidation date appended, as in 02016R0679-20160504.
N° 04Is there an official EUR-Lex search API or web service?+
Yes: the EUR-Lex web service, a SOAP search interface at https://eur-lex.europa.eu/EURLexWebService. It takes an expert query, such as TI ~ "data protection" AND FM_CODED = REG, and returns the matching documents’ metadata, up to 100 per page. You need to register with an EU Login account; registration is reviewed before access is granted, and each account has a daily call quota.
N° 05What is the Cellar RESTful API?+
Cellar is the Publications Office repository that feeds EUR-Lex. Its documents are addressable by CELEX number at http://publications.europa.eu/resource/celex/ followed by the number, and you choose the format by content negotiation: Accept: application/xhtml+xml for the XHTML text or application/zip;mtype=fmx4 for Formex XML, with a three-letter Accept-Language such as eng, which is mandatory. Metadata can be queried with SPARQL at https://publications.europa.eu/webapi/rdf/sparql. Neither needs registration or a key.
N° 06How do I get a EUR-Lex document as JSON?+
With LexAPI: POST a CELEX number to https://lex-api.com/api/v1/documentContent, or a pasted EUR-Lex link to /api/v1/documents/url, with your API key in the x-api-key header. You get the document as JSON — metadata, full text, and its articles, recitals and annexes as separate items. LexAPI is an independent service, not an official EU one; the Free plan starts with 500 credits, and a document read costs at most 5.

Sources: LexAPI’s own EUR-Lex and Cellar clients, and live checks against the Cellar SPARQL endpoint and content negotiation (November 2026). The EUR-Lex web service and Cellar are run by the Publications Office of the European Union; LexAPI is not affiliated with it.