Searching the Bible
BibleQL has three different ways to find verses, and picking the wrong one is the most common
source of surprise. This page covers search; the other two have their own guides.
Choosing among the three
| Query | Matching | Ordering | Use it for |
|---|---|---|---|
search | Case-insensitive substring | Canonical | Quick lookup of a literal phrase |
concordance | Stemmed word | Canonical, exhaustive | Word study, every occurrence |
semanticSearch | Meaning, via embeddings | By similarity | "Verses about forgiveness" |
How search matches
- GraphQL
- cURL
- Ruby
- Node.js
- Response
query {
search(translation: "eng-web", query: "love", limit: 5) {
bookName
chapter
verse
text
}
}
curl https://bibleql.org/graphql \
-H "Authorization: Bearer $BIBLEQL_API_KEY" \
-H "Content-Type: application/json" \
--data '{"query":"query { search(translation: \"eng-web\", query: \"love\", limit: 5) { bookName chapter verse text } }"}'
require "bibleql"
client = BibleQL::Client.new(
api_key: ENV.fetch("BIBLEQL_API_KEY"),
api_url: "https://bibleql.org/graphql"
)
results = client.search("love", translation: "eng-web", limit: 5)
results.each { |v| puts "#{v.book_name} #{v.chapter}:#{v.verse}" }
import { BibleQLClient } from "bibleql-js";
const client = new BibleQLClient({
apiKey: process.env.BIBLEQL_API_KEY!,
apiUrl: "https://bibleql.org/graphql",
});
const results = await client.search("love", {
translation: "eng-web",
limit: 5,
});
results.forEach((v) => console.log(`${v.bookName} ${v.chapter}:${v.verse}`));
{
"data": {
"search": [
{
"bookName": "Genesis",
"chapter": 22,
"verse": 2,
"text": "He said, “Now take your son, your only son, whom you love, even Isaac, and go into the land of Moriah. Offer him there as a burnt offering on one of the mountains which I will tell you of.”"
},
{
"bookName": "Genesis",
"chapter": 24,
"verse": 67,
"text": "Isaac brought her into his mother Sarah’s tent, and took Rebekah, and she became his wife. He loved her. Isaac was comforted after his mother’s death."
},
{
"bookName": "Genesis",
"chapter": 25,
"verse": 28,
"text": "Now Isaac loved Esau, because he ate his venison. Rebekah loved Jacob."
},
// ... 2 more
]
}
}
search performs a case-insensitive substring match on the verse text. That has concrete
consequences:
lovematcheslove,Love,belovedandlovingkindness— any verse whose text contains those letters.lovedoes not matchlovedas a separate concept; it matches it only becauselovedcontains the substringlove. Conversely, searchinglovedwill not findlove.- There is no stemming. Searching
runwill not findran. - There is no phrase or boolean syntax. The whole query string is one substring.
If you want linguistic matching — amor finding amores and amoroso — use
concordance, which runs through the translation's stemming
dictionary.
Results and limits
Results come back in canonical order (Genesis → Revelation, then chapter, then verse), not by relevance. There is no ranking.
The limit argument defaults to 25 and is capped at 100, server-side. Asking for 500
returns 100 without an error, so do not assume you received everything you requested.
search has no pagination. If you need every occurrence of a word rather than the first
hundred, that is exactly what concordance is for — it is exhaustive
and cursor-paginated.
Language behaviour
Substring matching is language-agnostic, so search works identically on every translation
with no index required. That is its main advantage: no setup, no per-translation caveats.
It is also why it cannot do anything clever. Case is ignored, so amor does find Amor — but
accents are not folded, so oracion will not find oración. If your users type without
accents, normalize their input against the translation's own spelling before searching, or use
concordance, which goes through a real text-search dictionary.
Practical guidance
- Looking for a phrase you can quote exactly →
search - Studying a word and its forms →
concordance - Describing an idea rather than wording →
semanticSearch - Need every match, not a sample →
concordance