The Urantia Book

Settings

Reading
Theme
Text size
Line spacing

Typeface

Width
Alignment
Show
Listening

Kept in this browser only.

The text API

Any site may keep its copy of the English text in step with this one, or fetch a passage or a paper from it by reference. The text is that of the Uversa Press edition, with its numerous corrections, and it is in the public domain; the edition as a whole, with its index, is licensed under CC BY-NC-SA 4.0. Its HTML marks the words of Jesus, which this site shows in red; the printed book does not.

It is at version 8, made on 2026-10-13: 4 parts, 197 papers, 1,626 sections and 14,586 paragraphs.

In short

GET https://ubsite.sigmaai.au/api/v1/text?since=0           the whole text, and its version
GET https://ubsite.sigmaai.au/api/v1/text?since=N           what has changed since version N
GET https://ubsite.sigmaai.au/api/v1/paragraphs/101:4.2-7   a passage, by reference
GET https://ubsite.sigmaai.au/api/v1/papers/101             a paper

Keep the version you are sent, and ask with it next time. A version changes only when a record does: a correction, an italic, the red letter, a reference. When nothing has, the reply is empty, so asking once a day costs nothing. The whole text is about 3 MB compressed, and a reply is compressed whenever your client accepts gzip, as every common one does.

A reply

This is the reply to a site holding version 7, as it would come today. The lists hold whole records, shown below; here they are only counted.

{
 "api": 1,
 "version": 8,
 "since": 7,
 "full": false,
 "made": "2026-10-13",
 "source": {
  "press": "5f95c312e679c1fc6c4d3d0f7a0b75535b8a641d"
 },
 "licence": {
  "text": "public domain",
  "credit": "requested, not required",
  "credit_line": "Text: the Uversa Press edition of The Urantia Book, https://ubsite.sigmaai.au/"
 },
 "parts": [],
 "papers": [],
 "sections": [],
 "paragraphs": [ 14,586 records ],
 "removed": {"parts": [], "papers": [], "sections": [], "paragraphs": []}
}

Applying a reply

  1. For each record in parts, papers, sections and paragraphs, replace yours with the same key, or add it. The key is ref for a section or a paragraph, and the number for a part or a paper.
  2. Delete each key listed under removed.
  3. If full is true, the reply is the whole text, so delete anything it does not contain. A reply is full when you ask from 0, or from a version this site has not made.
  4. Keep version, and send it as since next time.

The rest of a reply: since is the version it is relative to, 0 when it is full; made is the date of version; source is the commit of the Uversa Press text it was made from; and licence says what you may do with it.

The records

A paragraph:

{
 "ref": "147:4.4",
 "uf_ref": "147:4.4",
 "page_1955": "1650.5",
 "paper": 147,
 "section": 4,
 "paragraph": 4,
 "separator_before": null,
 "group_before": true,
 "kind": "prose",
 "setoff": false,
 "readings_1955": [],
 "html": "<span class=\"jesus\"><span class=\"mark\">“1.</span> <em>The level of the flesh.</em> Such a purely selfish and lustful interpretation would be well exemplified by the supposition of your question.</span>",
 "hash": "e552cd1f7dc75085"
}

And one where the 1955 printing reads otherwise: it set only Vertical in italics.

{
 "ref": "112:1.7",
 "uf_ref": "112:1.7",
 "page_1955": "1226.11",
 "paper": 112,
 "section": 1,
 "paragraph": 7,
 "separator_before": null,
 "group_before": true,
 "kind": "prose",
 "setoff": false,
 "readings_1955": [
  "<em>Vertical</em> depth"
 ],
 "html": "<span class=\"mark\">2.</span> <em>Vertical depth</em><span class=\"v1955\"></span> embraces the organismal drives and attitudes, the varying levels of self-realization and the general phenomenon of reaction to environment.",
 "hash": "4bb13f7934e75925"
}
ref
Paper, section and paragraph, as this site numbers them: /147:4.4 opens it here. The Foreword is paper 0, and each paper's introduction is section 0.
uf_ref
The same paragraph as the Urantia Foundation numbers it: see below.
page_1955
Where the paragraph begins in the 1955 first printing, whose pages the Foundation's printings keep: the page, then the paragraph on that page, "1109.3". The Foundation prints none beside 0:12.10, the Foreword's closing ACKNOWLEDGMENT; its "16.7" is where the 1955 printing has it, between 0:12.9 (16.6) and 0:12.11 (16.8).
paper, section, paragraph
The three numbers of ref.
separator_before
The separator the book prints before the paragraph, as its stars: "* * *", or "* * * * *" before the closing notes of Parts I, II and III; null where there is none. A separator is not a paragraph, and has no number of its own.
group_before
true where the paragraph begins a new group, as the 1955 printing sets one off; this site marks it ¶. false otherwise.
kind
"prose"; or "verse", a line of verse, which the book sets one to a line and does not fill: the psalm in 48:6, the song in 122:9, and the prayers of 144:3 and 144:5; or "heading", the one heading within the text, the Foreword's ACKNOWLEDGMENT, 0:12.10, which the book sets apart. The book indents each block of verse as one; a block begins with a line of verse that follows prose, or that has a separator before it.
setoff
true for a line of verse the book sets in further than the lines around it: the second line of each couplet of the Lord's Prayer, 144:3.4, 3.6, 3.8 and 3.10. false otherwise.
readings_1955
What the 1955 first printing reads where today's text departs from it, as the Uversa Press gives it, in HTML: one for each <span class="v1955"></span> in html, in the same order, and [] for most paragraphs. A marker stands just after the words that changed. Which of today's words a reading replaces is not recorded, and a long one is shortened with “…”, so show a reading beside the text, as this site does in a card at a small ring, and never in place of it. The SRT Committee's reasons for each change, which this site shows with it, are not part of the text and are not sent.
html
The text, in Unicode (curly quotes, em dashes), with its markup and nothing else: <em> for italics, <sup> for an exponent, <span class="jesus"> for the words of Jesus, <span class="mark"> around a list's number, an empty <span class="leader"></span> where the book prints a dot leader, and an empty <span class="v1955"></span> where the 1955 printing reads otherwise (see readings_1955). For plain text, strip the tags: what is left is the text exactly. The only entities there can be are &amp;, &lt; and &gt;, and the text holds none of those characters today, but unescape them all the same:
# Python
text = html.unescape(re.sub(r"<[^>]+>", "", record["html"]))

// JavaScript
const text = record.html.replace(/<[^>]+>/g, "")
  .replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
hash
For checking your copy: see below.

A section. Section 0, a paper's introduction, has no title.

{
 "ref": "139:9",
 "uf_ref": "139:10",
 "paper": 139,
 "section": 9,
 "title": "James and Judas Alpheus",
 "combined_with": 10,
 "hash": "73b934817e1e9cde"
}

A paper has paper, part (null for the Foreword), title and author. A part has part, label, title, sponsor and papers, its first and last.

Two numberings

This site numbers paragraphs as the Uversa Press edition does. 106 of them have other references in the Urantia Foundation's numbering, which every translation follows. If you join this text to other data by reference, join on uf_ref, not ref.

{
 "ref": "144:5.11",
 "uf_ref": "144:5.12",
 "page_1955": "1622.10",
 "paper": 144,
 "section": 5,
 "paragraph": 11,
 "separator_before": "* * *",
 "group_before": false,
 "kind": "verse",
 "setoff": false,
 "readings_1955": [],
 "html": "Our creative Parent, who is in the center of the universe,",
 "hash": "b2f5e94908f95c78"
}

Both number the Foreword's closing ACKNOWLEDGMENT 0:12.10, though the Foundation prints no number beside it.

A passage, or a paper

To quote a paragraph, or to show a passage or a paper, ask for it by reference. Write each reference whole, as this site numbers it, with commas between them:

GET https://ubsite.sigmaai.au/api/v1/paragraphs/101:4.2              a paragraph
GET https://ubsite.sigmaai.au/api/v1/paragraphs/101:4                a section
GET https://ubsite.sigmaai.au/api/v1/paragraphs/101:4.2-7            paragraphs 2 to 7 of 101:4
GET https://ubsite.sigmaai.au/api/v1/paragraphs/101:4.7-5.2          from 101:4.7 to 101:5.2
GET https://ubsite.sigmaai.au/api/v1/paragraphs/101:4-6,5:1.3,61:4   several, from anywhere in the book
GET https://ubsite.sigmaai.au/api/v1/papers/101                      a paper
GET https://ubsite.sigmaai.au/api/v1/papers/0,101-103                several; the Foreword is Paper 0

A range runs in the order of the book from its first reference to its last, across sections and papers if need be, 101:4.7-102:1.3. Its end is written like its start, with as much as changes: 101:4.2-7, 101:4.7-5.2, 101:4-6, 101:4-102:1. An en dash will do for the hyphen. At most 100 references are taken at a time.

The reply holds the records /text sends, the same to the byte, hashes and all. The paragraphs come in the order of the book, each once, however the references overlap. With them come the section, the paper and the part each stands in, so that a quotation can be headed without a second request. This is the reply to /paragraphs/101:4.7-5.2, its records counted:

{
 "api": 1,
 "version": 8,
 "made": "2026-10-13",
 "source": {
  "press": "5f95c312e679c1fc6c4d3d0f7a0b75535b8a641d"
 },
 "licence": {
  "text": "public domain",
  "credit": "requested, not required",
  "credit_line": "Text: the Uversa Press edition of The Urantia Book, https://ubsite.sigmaai.au/"
 },
 "parts": [ 1 record ],
 "papers": [ 1 record ],
 "sections": [ 2 records ],
 "paragraphs": [ 6 records ]
}

It has no since, full or removed: it is not a step in keeping a copy, and its version is only the version its records are from. Never keep it as the version of a copy.

The index writes 61:4.3,4 for two paragraphs of one section. Here that would mean 61:4.3 and the whole of Paper 4, so /paragraphs/ refuses a bare number with a 400 that says so. Write 61:4.3,61:4.4 or 61:4.3-4, and ask /papers/4 for the paper.

To ask by the Foundation's numbering, add ?numbering=uf: /paragraphs/144:5.108?numbering=uf is this site's 144:5.102, and /paragraphs/139:10?numbering=uf is its 139:9. The records are the same either way, and each carries both references. The numbers the Foundation gives the separators of 134:6 and 144:5 name no paragraph. Asking for one is a 404, as is any reference not in the text, and the reply lists every such reference under missing. Papers are numbered alike, so /papers/ takes the switch and changes nothing.

From a page on any site:

const r = await fetch("https://ubsite.sigmaai.au/api/v1/paragraphs/101:4.2");
const {papers, sections, paragraphs} = await r.json();
// papers[0].title, sections[0].title, paragraphs[0].html

A client in Python

With nothing but the standard library. It keeps the text in one JSON file.

import gzip, json, pathlib, urllib.request

BASE = "https://ubsite.sigmaai.au/api/v1"
AGENT = "MySite/1.0 (+https://example.org)"       # your site's name, please
STORE = pathlib.Path("urantia-book-en.json")
KEY = {"parts": "part", "papers": "paper", "sections": "ref", "paragraphs": "ref"}

have = json.loads(STORE.read_text()) if STORE.exists() else {"version": 0, "records": {}}
req = urllib.request.Request(f"{BASE}/text?since={have['version']}",
                             headers={"User-Agent": AGENT, "Accept-Encoding": "gzip"})
with urllib.request.urlopen(req) as r:
    body = r.read()
    if r.headers.get("Content-Encoding") == "gzip":
        body = gzip.decompress(body)
reply = json.loads(body)
if reply["full"]:
    have["records"] = {}
for kind, key in KEY.items():
    for rec in reply[kind]:
        have["records"][f"{kind}/{rec[key]}"] = rec
    for gone in reply["removed"][kind]:
        have["records"].pop(f"{kind}/{gone}", None)
have["version"] = reply["version"]
STORE.write_text(json.dumps(have, ensure_ascii=False))
print(f"version {reply['version']}: {sum(len(reply[k]) for k in KEY)} records")

Checking your copy

A record's hash is the first 16 hex digits of the SHA-256 of the record without its hash, as JSON with its keys sorted and no spaces, in UTF-8. Recompute it over what you store, and a record that has gone wrong in your copy shows itself:

# Python
rec = dict(record); del rec["hash"]
hashlib.sha256(json.dumps(rec, ensure_ascii=False, sort_keys=True,
               separators=(",", ":")).encode()).hexdigest()[:16]

// JavaScript
const {hash, ...rec} = record;
const json = JSON.stringify(Object.fromEntries(Object.entries(rec).sort(([a], [b]) => a < b ? -1 : 1)));
const hex = [...new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(json)))]
  .map(b => b.toString(16).padStart(2, "0")).join("").slice(0, 16);

Please

Questions, or to say that your site uses the API: tigran.aivazian@urantiabook.org.

Other endpoints

GET /api/v1
The current version, the counts, the Uversa Press commit this database was built from, and these links.
GET /api/v1/versions
Every version: when it was made, from which commit, and how many records it changed.

Errors come back as JSON with a status, and a message in error. A 400 is for a since that is not a version number, or a reference that cannot be read. A 404 is for an address that is not an endpoint, or for references not in the text, listed under missing. Every reply may be read from a page on another site (Access-Control-Allow-Origin: *).

Versions

The counts are of records: parts, papers, sections and paragraphs. Version 1 is the whole text, so it counts every one of them.

VersionMadeText commitNew or changedRemoved
82026-10-135f95c31 14,5860
72026-10-12806c7ac 14,5860
62026-10-12806c7ac 14,5860
52026-10-12806c7ac 14,5860
42026-10-12806c7ac 10
32026-10-11806c7ac 14,5860
22026-10-11806c7ac 14,5860
12026-10-11806c7ac 16,4130