ESV Bible Web Service

ESV Bible Web Service API (Version 2)

What’s New

REST Interface

The base url for all REST requests is: http://www.esvapi.org/v2/rest/

Certain variables are required to receive the desired response, depending on your desired action:

For passageQuery (look up a passage):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.
passage The passage you want to display. It accepts a wide variety of input formats (e.g., Isaiah 1, Isa 1, and Is 1 all go to Isaiah 1).

For query (look up a passage or show word-search results, depending on the query):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.
q The passage you want to display or string you want to search for. It is weighted toward finding passages, so a search for is shows you Isaiah 1. To override this behavior, see below.

For readingPlanQuery (retrieve passages from our Devotions section. More…):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.

For queryInfo (parse and display information about your query, including identify whether it is a passage reference or a word search. More…):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.
q The string you want to parse.

For readingPlanInfo (parse and display information about the reading plan for a given date. More…):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.

For verse (display a random verse from a preselected list, or specify verse(s). More...):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.

For dailyVerse (display a verse that changes every day. More…):

 Variable  Description
key Your access key. For testing purposes, you can use the key TEST. For general-purpose queries, you can use the key IP.

Additionally, for passageQuery and readingPlanQuery, you can set a number of optional variables, depending on your desired output format. (See below.)

Sample Queries using the IP key

HTML Output

HTML is the default output and will appear unless output-format is specified. To make full use of the text, you will probably want to link a CSS stylesheet to your page, either one you've created or ours (http://www.gnpcb.org/esv/assets/style/text.css). This stylesheet contains close to the minimum markup needed to render the text accurately.

The following options all take a Boolean value of true or false (or 1 or 0).

Option Default Description
include-passage-references true Include <h2>s that indicate which passage is being displayed. For example: Isaiah 53:1-5.
include-verse-numbers true Show verse numbers in the text.
include-footnotes true Include footnotes and references to them in the text.
include-footnote-links true If you have set include-footnotes to true, set this option to false to turn off the links to the footnotes within the text. The footnotes will still appear at the bottom of the passage. If include-footnotes is false, this parameter does not do anything.
include-headings true Include section headings. For example, the section heading of Matthew 5 is The Sermon on the Mount.
include-subheadings true Include subheadings. Subheadings are the titles of psalms (e.g., Psalm 73's A Maskil of Asaph), the acrostic divisions in Psalm 119, the speakers in Song of Solomon, and the textual notes that appear in John 7 and Mark 16.
include-surrounding-chapters false Show links under the reference to the previous, current (if not showing the whole chapter) and next chapters in the Bible. The link points to the ESV website, but you can modify it by changing the link-url parameter.
include-word-ids false Include a <span> tags surrounding each word with a unique id. The id has several parts; the id "w40001002.01-1" consists of: the letter w (needed for valid XHTML ids), an eight-digit verse identifier (40001002 indicates Matthew 1:2), a period (.), a two-digit word identifier (01), and a hyphen followed by a number (this number is incremented with each passage; it starts with 1). Footnotes do not have word ids.
link-url http:// www.gnpcb.org/ esv/search/ Where embedded links to other passages should point. It currently applies only when include-surrounding-chapters is set to true.
include-audio-link true Include a link to the audio version of the requested passage. The link appears in a <small> tag in the passage's identifying <h2>.
audio-format flash Takes a value of flash, mp3, real, or wma to indicate the format of the audio. It defaults to flash, but the default could change; if you have a strong preference for one of these formats, we recommend that you specify it explicitly. We recommend flash as the most flexible; an embedded Flash player is included in the text. When the audio-version is hw or mm, the mp3 option includes a link to an MP3 file. The other two options, real and wma, only have New Testament recordings by Marquis Laughlin available. (The real option refers to RealAudio, and wma refers to Windows Media.)
audio-version hw Which recording to use. The options are: hw (David Cochran Heath [Hear the Word], complete Bible) mm (Max McLean, complete Bible), ml (Marquis Laughlin, New Testament only), ml-mm (David Cochran Heath for Old Testament, Marquis Laughlin for New Testament), and ml-mm (Max McLean for Old Testament, Marquis Laughlin for New Testament). Only affects the output if audio-format is flash or mp3. (David Cochran Heath and Max McLean's versions are only available in these two formats.)
include-short-copyright true Each passage from the ESV needs to include the letters "ESV" at the end of the passage. To turn off this behavior, set this option to false.
include-copyright false Show a copyright notice at the bottom of the text. Any page that shows the ESV text from this service needs to include a copyright notice, but you do not need to include it with each passage. Best practice is probably to include the copyright manually on your page, rather than download it every time. This option is mutually exclusive with include-short-copyright, which overrides include-copyright.

Sample Output (line breaks added for clarity)

<div class="esv">
<h2>Matthew 22:43 - 23:1</h2>
<div class="esv-text">
  <p class="virtual"><span class="verse-num">43&nbsp;</span>He said to them,
    <span class="woc">&#8220;How is it then that David, in the Spirit,
    calls him Lord, saying,</span></p>

  <div class="block-indent">
    <p class="line-group"><span class="verse-num woc">44&nbsp;</span>
      <span class="woc">&#8220;&#8216;The Lord said to my Lord,<br />
      Sit at my right hand,<br />
      <span class="indent"></span>until I put your enemies under
      your feet&#8217;?</span></p>
  </div>

  <p class="same-paragraph"><span class="verse-num woc">45&nbsp;</span>
    <span class="woc">If then David calls him Lord, how is he his son?&#8221;</span>
    <span class="verse-num">46&nbsp;</span>And no one was able to answer him a word,
    nor from that day did anyone dare to ask him any more questions.</p>

  <h3>Seven Woes to the Scribes and Pharisees</h3>
  <p><span class="chapter-num">23:1</span>Then Jesus said
    to the crowds and to his disciples,</p>
</div>

<p class="copyright">The Holy Bible, English Standard Version
  copyright &copy;&nbsp;2001 by <a href="http://www.crosswaybibles.org">Crossway
  Bibles</a>, a publishing ministry of Good News Publishers. Used by permission. All rights
  reserved. <a
  href="http://www.gnpcb.org/page/esv.copyright">Quotation information</a>.</p>
</div>

Crossway XML Output

This format shows you how we store the text in our database. It has fewer options because we assume that you will have to transform the output anyway, so you will be able to remove the elements you don't need. You can find a description of the schema here. We designed it to be easily transformed into HTML and other paragraph-based markup. See the PHP code we use to transform the XML into HTML. Note that this script only formats the data in the <content> tags, and it doesn't handle footnotes.

Set the option output-format to crossway-xml-1.0 if you want to display this format.

Most of the following options take a Boolean value of true or false (or 1 or 0).

Option Default Description
include-xml-declaration false Include a <?xml version="1.0" ?> at the top of the document.
include-doctype true Include a DOCTYPE declaration. Note that it links to a DTD that only explains the character entities, not the elements.
include-quote-entities true The original XML files contain an elaborate system of marking where quotations begin and end. This information is unnecessary for most purposes. Leaving this option set to true transforms the quotations from <q> elements to the entities referenced in the DTD (e.g., &ldblquot; for an opening double quotation mark). Setting this option to false leaves in the <q> tags, as described in the XML Schema.
include-simple-entities false Translates character entities to native XML entities (e.g., &ldblquot; becomes &quot;) for non-DTD-aware parsers. You can see the specific transformations we do in our PHP function translate_entities_to_simple_xml(). If you also disable the option include-quote-entities, the quote entities are translated to <q> tags before applying this transformation.
include-cross-references false Currently, the cross-references don't point to anything, so there's little reason to include them.
include-line-breaks true Include line breaks in the XML output. It doesn't make any functional difference; it's just easier to read.
include-word-ids false Include word ids (<w> tags) around each word in the text. The wid attribute consists of an eight-digit verse identifier, followed by a period (.) and a two-digit word identifier. The wids are unique for each word in the Bible; however, if you call the same passage more than once, the wids will repeat. In other words, two instances of Matthew 1:2 will have <w> tags with identical wid values.
include-virtual-attributes false All begin- and end- tags must match--for example, a <begin-paragraph/> tag always has a corresponding <end-paragraph/> tag. If a tag had to be added programmatically (for example, if the requested passage ends in the middle of a paragraph), a virtual="virtual" attribute is added to the tag (for example, <end-paragraph virtual="virtual"/>). If you want to know whether a given tag was added programmatically and doesn't really exist in the text, set this option to true.
base-element verse-unit Set to paragraph to transform the output from verse-unit-based markup (<verse-unit> <begin-block-indent/> <begin-paragraph/> <begin-line/>...<end-line/> <end-paragraph/> <end-block-indent/> </verse-unit>) to paragraph-based markup (<begin-verse-unit/> <block-indent> <paragraph><line>...</line></paragraph> </block-indent> <end-verse-unit/>). In doing so, you lose a little bit of information--you can no longer tell whether the end of a passage indicates the true end of a paragraph or block indent in the text, or whether it was put there to allow the proper closing of tags. That is to say, there is no longer <end-(paragraph|block-indent) class="virtual"/>.

Sample Output (formatting added for clarity)

<?xml version="1.0" ?>
<!DOCTYPE crossway-bible SYSTEM
    "http://www.gnpcb.org/esv/share/schemas/crossway.base.entities.dtd">
<crossway-bible class="passage-query">
<passage>
  <reference>Matthew 22:43 - 23:1</reference>
  <surrounding-chapters>
    <previous>Matthew 21</previous>
    <current>Matthew 22 - 23</current>
    <next>Matthew 24</next>
  </surrounding-chapters>
  <content>
    <verse-unit unit-id="40022043">
      <begin-paragraph class="virtual"/>
        <verse-num>43</verse-num>He said to them,
          <woc>&ldblquot;How is it then that David, in the Spirit, calls
               him Lord, saying,
          </woc>
      <end-paragraph/>
    </verse-unit>
    <verse-unit unit-id="40022044">
      <begin-block-indent/>
        <begin-paragraph class="line-group"/>
          <begin-line/>
            <verse-num class="woc">44</verse-num>
            <woc>&ldblquot;&lquot;The Lord said to my Lord,
          <end-line class="br"/>
          <begin-line/>Sit at my right hand,<end-line class="br"/>
          <begin-line class="indent"/>until I put your enemies
             under your feet&rquot;?
            </woc>
          <end-line/>
        <end-paragraph/>
      <end-block-indent/>
    </verse-unit>
    <verse-unit unit-id="40022045">
      <begin-paragraph class="same-paragraph"/>
        <verse-num class="woc">45</verse-num>
        <woc>If then David calls him Lord, how is he his
             son?&rdblquot;
        </woc>
    </verse-unit>
    <verse-unit unit-id="40022046">
       <verse-num>46</verse-num>And no one was able to answer him
       a word, nor from that day did anyone dare to ask him any
       more questions.
       <end-paragraph/>
       <end-chapter/>
    </verse-unit>
    <verse-unit unit-id="40023001">
       <begin-chapter num="23"/>
       <heading>Seven Woes to the Scribes and Pharisees</heading>
       <begin-paragraph/>
         <verse-num begin-chapter="23">1</verse-num>Then Jesus
         said to the crowds and to his disciples,
       <end-paragraph class="virtual"/>
    </verse-unit>
  </content>
</passage>

<copyright>The Holy Bible, English Standard Version copyright (c)2001
  by Crossway Bibles, a publishing ministry of Good News Publishers. Used by permission.
  All rights reserved. http://www.crosswaybibles.org
</copyright>

</crossway-bible>

Plain Text Output

This format is suitable for use in plain-text environments such as email.

Set the option output-format to plain-text to display this format.

The following options all take a Boolean value of true or false (or 1 or 0) except for line-length, which takes an integer.

Option Default Description
include-passage-references true Include a line saying which passage is being displayed. In the example below, Matthew 22:43 - 23:1.
include-first-verse-numbers true Show the verse number at the beginnings of chapters. In the example below, [23:1].
include-verse-numbers true Show verse numbers in brackets.
include-footnotes true Show references to footnotes in the text in parentheses, and include the text of the footnotes at the bottom of the text.
include-short-copyright true Each passage from the ESV needs to include the letters "ESV" at the end of the passage. To turn off this behavior, set this option to false.
include-copyright false Show a copyright notice at the bottom of the text. Any page that shows the ESV text from this service needs to include a copyright notice, but you do not need to include it with each passage. Best practice is probably to include the copyright manually on your page, rather than download it every time. This option is mutually exclusive with include-short-copyright, which overrides include-copyright.
include-passage-horizontal-lines true Include a line of equals signs (===) above the beginning of each passage.
include-heading-horizontal-lines true Include a line of underscores (___) above each section heading.
include-headings true Include section headings. In the below example, Seven Woes to the Scribes and Pharisees.
include-subheadings true Include subheadings. Subheadings are the titles of psalms (e.g., Psalm 73's A Maskil of Asaph), the acrostic divisions in Psalm 119, the speakers in Song of Solomon, and the textual notes that appear in John 7 and Mark 16.
include-selahs true Include Selahs, which are found mostly in the Psalms (e.g., Psalm 46:3).
include-content-type true Adds a Content-Type: text/plain HTTP header. Set to false if you want the default content type. (For example, in an RSS feed you want the content type to remain text/xml).
line-length 74 How long to make each line. Can be any integer 36 and over. Set to 0 for unlimited length--each paragraph or line of poetry will be on a separate line.

Sample Output

=====================================
Matthew 22:43 - 23:1
   [43]He said to them, "How is it then that 
David, in the Spirit, calls him Lord, saying,

  [44]"'The Lord said to my Lord,
  Sit at my right hand,
    until I put your enemies under your feet'?

[45]If then David calls him Lord, how is he his 
son?" [46]And no one was able to answer him a 
word, nor from that day did anyone dare to ask 
him any more questions.
_____________________________________
Seven Woes to the Scribes and Pharisees

   [23:1]Then Jesus said to the crowds and to his 
disciples,

The Holy Bible, English Standard Version 
copyright (c)2001 by Crossway Bibles, a division 
of Good News Publishers. Used by permission. All 
rights reserved. http://www.crosswaybibles.org

MP3 Output

This format returns an mp3 file of the requested passage(s). You can use any valid passage reference to play up to approximately 200 verses. The audio is, of course, copyrighted and subject to the same Terms of Service as the rest of the API.

Strictly speaking, a call to this API returns a 302 (Redirect) HTTP status and a Location header that provides the URL of the actual MP3. The content of the response also points to this URL.

Only the Hear the Word audio is available. Setting audio-version has no effect. There are no other parameters.

Sample Output

Request: http://www.esvapi.org/v2/rest/passageQuery?key=IP&passage=1cor3:16&output-format=mp3

Including HTTP Headers

HTTP/1.1·302·Found
Location:·http://stream.esvmedia.org/mp3-play/hw/46003016.mp3

http://stream.esvmedia.org/mp3-play/hw/46003016.mp3

Following the redirect to the indicated URL provides

Function query

This function takes any of the above arguments except output-format, which is always HTML. (For passage pages, you can use the HTML formatting functions above.) It can also take a number of optional arguments:

Option Default Description
q   The string to search for.
passage   Put a string in here to force a passage search. This behavior is otherwise identical to passageQuery.
words   Put a string in here to force a word search.
phrase   Search for an exact phrase. In general, you can also surround words in q with quotation marks to mimic this functionality.
not-words   Exclude verses containing certain words. Can only be used in conjunction with the words and phrase options.
scope [Complete Bible] Limit your search to certain sections of the Bible. Accepts the predefined inputs listed in the dropdown menu on the Advanced Search page.
matches   [Empty] matches anywhere in words (the finds father). beginning matches beginnings of words (the finds there). exact matches exact words only (the only finds the). The latter two options are slower.
search-text all all searches the complete text of the Bible, including headings and footnotes. Set to text to exclude headings and footnotes.
page 1 If the results span more than one page (e.g., 27 results were found, but only 25 are shown per page), set the page number (starting at 1) to show a different page of results.
link-url /esv/search/ Specifies what link to use when linking from the search results page to another page. If the page that handles your requests is named bible.search.php, for example, set this option to bible.search.php.
results-per-page 25 How many search results to show per page. Must be between 2 and 100 (inclusive).

On your server, you will probably have to catch at least the page variable that's submitted. In PHP, you might do the following:

<?php
	$options = '';
	foreach ($_GET as $key => $value)
	{
		$options .= "&$key=" . urlencode($value);
	}
	#continue as below, but use $options .= ... instead of $options =
?>

Function readingPlanQuery

This function takes any of the above arguments, depending on your desired output format. It can also take two optional arguments:

Option Default Description
date Today's date Get the reading plan for a certain date. Should be in YYYY-MM-DD format. The date changes at midnight US Central Time (GMT -0500).
reading-plan one-year-tract

Specifies which reading plan to use. Possibilities are:

  • bcp
  • lsb
  • esv-study-bible
  • every-day-in-the-word
  • one-year-tract
  • outreach
  • outreach-nt
  • through-the-bible

For more information about these reading plans, please see our Devotions area.

start-date   Specify a start date for the reading plan if you want to begin your readings at the beginning of the plan on dates besides January 1. Should be in YYYY-MM-DD format.

You can, of course, create your own Bible reading plan and query our server for the appropriate passages each day.

Function queryInfo

This function takes two arguments, a key and a query, and returns information about the query. One of the most difficult parts of implementing a Bible search engine comes from having to parse the user's query and decide whether the query is a passage reference or a word search. You can use our search engine to decide for you.

Option Default Description
q   The words or passage you want to parse.

It returns an XML document with a structure similar to the following. The query was for ha. (Indentation added for clarity.)

<crossway-bible class="query-type">
   <query>ha</query>
   <query-type>passage</query-type>
   <readable>Habakkuk 1</readable>
   <unit>35001001-35001017</unit>
   <verse-count>17</verse-count>
   <is-complete-chapter>1</is-complete-chapter>
   <alternate-query-type>word-search</alternate-query-type>
   <alternate-result-count>18803</alternate-result-count>
   <warnings>
      <warning>
         <code>ambiguous-book</code>
         <readable>It looks like the book abbreviation used in this search can stand for for more than one book. We're showing you <strong>Habakkuk 1</strong>. You may also want to see:<br />&#8226; <a href="http://www.gnpcb.org/esv/search/?q=Haggai+1">Haggai 1</a></readable>
      </warning>
   </warnings>
</crossway-bible>

Element Description
crossway-bible Always has a class query-type for this function.
error (Not shown.) Some sort of fatal error, usually indicating an invalid key or no query. The content of this tag is a human-readable error message.
query The text of your original query.
query-type Either passage or word-search. Tells you how we understood your query.
readable Appears if the query-type is passage. Gives a normalized passage reference (full book names and chapter references) that any Bible search engine should be able to understand.
unit Appears if the query-type is passage. Numerically identifies the verses returned. Each unit component is 8 characters long: the first two characters identify the book (01-66), the next three characters identify the chapter (001-150), and the final three characters identify the verse (001-176). Hyphens (-) indicate a range of verses; commas (,) indicate separate passages.
result-count Appears if the query-type is word-count. Tells how many times the word appears in the ESV text (up to 1,000).
is-complete-chapter Appears if the query-type is passage. Has a value of 1 if the passage references refer only to complete chapters. Has a value of 0 if any of the passage references refer to a partial chapter.
verse-count Appears if the query-type is passage. Indicates the number of verses that the query would result in (up to 31,086). Note that if you then call passageQuery or query, you will only receive up to 500 verses at a time.
alternate-query-type, alternate-result-count If a passage reference could also be a word (as above, or, e.g., when someone searches for mark), these two tags appear set to word-search and the number of times the word appears in the ESV, respectively.
warnings Container tag. Doesn't appear in most queries. Can contain multiple <warning> tags. You can safely ignore these.
warning Contains a <code> and a <readable> tag.
warning > code The error code that pertains to the error. A complete list is forthcoming.
warning > readable An HTML human-readable description of the error. Any links in the code point to our site, but you can manipulate them to point wherever you wish.

Function readingPlanInfo

This function provides information about the readings for a given day. It doesn't return any Bible text. It has two optional arguments:

Option Default Description
date Today's date Get the reading plan for a certain date. Should be in YYYY-MM-DD format (e.g., 2014-09-17 for today). The date changes at midnight US Central Time (GMT -5 or -6).
reading-plan one-year-tract Specifies which reading plan to use. Possibilities are one-year-tract, through-the-bible, every-day-in-the-word, and bcp. For more information about these reading plans, please see our Devotions area.
start-date   Specify a start date for the reading plan if you want to begin your readings at the beginning of the plan on dates besides January 1. Should be in YYYY-MM-DD format.

It returns an XML document with a structure similar to the following. (Indentation added for clarity.)

Request URL.

Response:

<crossway-bible class="reading-plan-info">
   <date>20061225</date>
   <plan>bcp</plan>
   <id>1.28</id>
   <url>http://www.gnpcb.org/esv/devotions/bcp/?date=2006-12-25</url>
   <info>
      <psalm-1>Ps. 2,85</psalm-1>
      <psalm-2>Ps. 110:1-5,6-7,Ps. 132</psalm-2>
      <ot>Zech. 2:10-13</ot>
      <nt>1 John 4:7-16</nt>
      <gospel>John 3:31-36</gospel>
      <liturgical>
         <season>Christmas</season>
         <week>Christmas</week>
         <day>Christmas Day</day>
      </liturgical>
      <raw>Ps. 2, 85; Ps. 110:1-5(6-7), Ps. 132; Zech. 2:10-13; 1 John 4:7-16; John 3:31-36</raw>
   </info>
</crossway-bible>

Element Description
crossway-bible Always has a class reading-plan-info for this function.
error (Not shown.) Some sort of fatal error, usually indicating an invalid key or no query. The content of this tag is a human-readable error message. An <error> will be the only element returned.
date The date (in YYYYMMDD format) used in the query.
start-date If the start-date parameter was sent, shows the date used as January 1.
plan The reading plan id.
url The URL to access the day's reading on the ESV site.
id A unique identifier for the day within each reading plan. An <id> always occurs only once in a given calendar year.
info Contains an XML structure that varies depending on the reading plan. This structure contains exactly what we store in our database. For the bcp plan, the <liturgical> element will always contain exactly one <season>, 0 or 1 <week>s, and 0 or 1 <day>s.

Function verse

This function resembles passageQuery, except the additional formatting options described in dailyVerse are available. It is designed for short passages (1-5 verses), but the requested passages can be up to 500 verses in length. If you don't include a passage, it picks a verse at random from a preselected list of verses. (See the RSS Feed page for a list.) This function takes any of the arguments related to its output format, depending on your desired output format. It can also take two optional arguments:

Option Default Description
passage A random passage Get a specific passage or group of passages (e.g., Matthew 5:1,3,5).
seed A random number You can send your own seed to the random number generator if you want to get a specific result consistently. (For example, dailyVerse simply calls this function using the current date as the seed.)

For example, the following url:

http://www.esvapi.org/v2/rest/verse?key=IP&passage=John+5:25&include-footnotes=false

Retrieves the following (the &#8221; (a closing double quotation mark) at the end is added by the script; it doesn't exist in the text):

<h2>John 5:25</h2>
<div class="esv-text"><p><span class="woc">&#8220;Truly, truly, I say to you, an hour is coming, and is now here, when the dead will hear the voice of the Son of God, and those who hear will live.&#8221;</span> (<a href="http://www.esv.org" class="copyright">ESV</a>)</p>
</div>

Function dailyVerse

This argument retrieves a verse at random from the verses we've collected. The verse rolls over at midnight U.S. Central Time (GMT -5 or -6). This function takes any of the arguments related to its output format, depending on your desired output format. You probably want to set include-footnotes to false. For a list of verses, please see the RSS Feed page. Additionally, you can set the following parameters:

Option Default Description
include-headings false Whether to include the section headings (e.g., Jesus Feeds the Five Thousand in John 6).
begin-character An empty string If the first letter of the verse is lower-case, indicating that the verse begins in the middle of a sentence, you can prepend a string to the verse. For example, you might set this option to &ellipsis; or ... to begin such verses with an ellipsis.
correct-capitalization true If the first letter of the verse is lower-case, setting this option to true will upper-case it.
correct-end-punctuation true If the verse ends with anything besides a period, question mark, or exclamation mark (for example, a comma, semicolon, or dash), it replaces the ending punctuation with whatever you set in end-character.
end-character &ellipsis4; If the verse ends with anything besides a period, question mark, or exclamation mark (for example, a comma, semicolon, or dash), the ending punctuation will be replaced with this string.
correct-quotes true Balances quotes. If a quotation beginning in a previous verse ends in the current verse, an opening quotation mark is added to the beginning of the verse. Similarly, an ending quotation mark is added to the end of the verse if the quotation begins in the verse but extends beyond the end of the verse. So, all quotations have both beginning and ending marks.

Sample Code

The following code is offered "as-is." It may or may not work on your system.

Perl

REST

use LWP::Simple;
my $key = "IP";
my $passage = "Matthew 5";
my $options = "include-verse-numbers=false";
my $output = get("http://www.esvapi.org/v2/rest/passageQuery?key=$key&passage=$passage&$options");
print $output;

PHP

REST

If you have Curl installed with PHP, you can use the following:

<?php
  $key = "IP";
  $passage = urlencode("john 3:16");
  $options = "include-passage-references=false";
  $url = "http://www.esvapi.org/v2/rest/passageQuery?key=$key&passage=$passage&$options";
  $ch = curl_init($url); 
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  $response = curl_exec($ch);
  curl_close($ch);
  print $response;
?>

If your server allows remote fopen (allow_url_fopen), you can use the following (thanks to David Sanders for this code):

<?php
  $key = "IP";
  $passage = urlencode("john 3:16");
  $options = "include-passage-references=false&audio-format=flash";
  $url = "http://www.esvapi.org/v2/rest/passageQuery?key=$key&passage=$passage&$options";
  $data = fopen($url, "r") ;

  if ($data)
  {
     while (!feof($data))
     {
        $buffer = fgets($data, 4096);
        echo $buffer;
     }
     fclose($data);
  }
  else
  {
     die("fopen failed for url to webservice");
  }
?>

VB.NET

REST

Thanks to Charles Cherry for this and the C# code.

Dim strURL as New StringBuilder()
With strURL
    .Append("http://www.esvapi.org/v2/rest/passageQuery")
    .Append("?key=IP")
    .Append("&passage=" & Server.URLEncode("Matthew 5"))

    .Append("&include-headings=true")
End With
Dim objWebClient as New WebClient()
Dim objUTF8 as New UTF8Encoding()
Response.Write(objUTF8.GetString(objWebClient.DownloadData(strURL.ToString())))

C#

REST

StringBuilder sUrl = new StringBuilder();
sUrl.Append("http://www.esvapi.org/v2/rest/passageQuery");
sUrl.Append("?key=IP");
sUrl.Append("&passage=" + Server.UrlEncode("Matthew 5").ToString());

sUrl.Append("&include-headings=true");

WebRequest oReq = WebRequest.Create(sUrl.ToString());
StreamReader sStream = new StreamReader(oReq.GetResponse().GetResponseStream());

StringBuilder sOut = new StringBuilder();
sOut.Append(sStream.ReadToEnd());
sStream.Close();

Response.Write(sOut.ToString());

WCF (.NET 3.0)

David Betz has written a WCF proxy for the web service.

ASP

REST

Thanks to Simon Job for this code.

<%
  'Reference Search
  key = "IP"
  strSearch = "John 1"
  passage = Server.URLEncode(strSearch)
  options = "include-passage-references=true"
  set objHTTP = Server.CreateObject("Microsoft.XMLHTTP")
  objHTTP.open "GET", "www.esvapi.org/v2/rest/passageQuery?key=" & _
    key & "&passage=" & passage & "&" & options, false
  objHTTP.send
  Response.Write(objHTTP.responseText)
%>

Additionally, Jeff Owens has made available extensive ASP sample code for both normal searches and reading plans. More...

ColdFusion

REST

Thanks to David Scarbrough for this code.

<cfset key = "IP">
<cfset passage = "2 Tim 3:16">
<cfset options = "include-verse-numbers=false">
<cfhttp
  url = "http://www.esvapi.org/v2/rest/passageQuery?key=#key#&passage=#passage#&#options#"
  method = "get">
</cfhttp>
<cfoutput>#cfhttp.fileContent#</cfoutput>

Java

Thanks to Brian Wohlin for this code.

JDK Version 5.0

package org.esv.bible.service;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;

public class ESVService {

  public String getPassage(String book, String chapter) throws Exception {
    StringBuilder urlStringBuilder = new StringBuilder();
    urlStringBuilder.append("http://www.esvapi.org/v2/rest/passageQuery");
    urlStringBuilder.append("?key=IP");
    urlStringBuilder.append("&passage="
        + URLEncoder.encode(book + " " + chapter, "ISO-8859-1"));

    urlStringBuilder.append("&include-headings=true");

    URL esvURL = new URL(urlStringBuilder.toString());
    InputStream esvStream = esvURL.openStream();

    StringBuilder outStringBuilder = new StringBuilder();
    int nextChar;

    while ((nextChar = esvStream.read()) != -1) {
      outStringBuilder.append((char) nextChar);
    }

    esvStream.close();

    return outStringBuilder.toString();
  }

}

As a Servlet (Using JDK 1.3.1)

package org.esv.bible.service;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ESVServlet extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    doPost(req, resp);
  }

  public void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    String book = req.getParameter("book");
    String chapter = req.getParameter("chapter");
    StringBuffer urlStringBuffer = new StringBuffer();
    urlStringBuffer.append("http://www.esvapi.org/v2/rest/passageQuery");
    urlStringBuffer.append("?key=IP");
    urlStringBuffer.append(
      "&passage=" + URLEncoder.encode(book + " " + chapter));

    urlStringBuffer.append("&include-headings=true");

    URL esvURL = new URL(urlStringBuffer.toString());
    InputStream esvStream = esvURL.openStream();

    StringBuffer outStringBuffer = new StringBuffer();
    int nextChar;

    while ((nextChar = esvStream.read()) != -1) {
      outStringBuffer.append((char) nextChar);
    }

    esvStream.close();
    PrintWriter out = resp.getWriter();
    out.print(outStringBuffer.toString());
  }

}

Ruby

Thanks to Richard Kilmer for this code.

#!/usr/local/bin/ruby
puts "Welcome to ESV bible passage lookup."
puts "Enter the passage (i.e. Rom 3:15-20) or 'exit' to end."

require 'net/http'

class ESV
  def initialize(key)
    @options = ["include-short-copyright=0",
                "output-format=plain-text",
                "include-passage-horizontal-lines=0",
                "include-heading-horizontal-lines=0"].join("&")
    @base_url = "http://www.esvapi.org/v2/rest/passageQuery?key=#{key}"
  end

  def doPassageQuery(passage)
    passage = passage.gsub(/\s/, "+")
    passage = passage.gsub(/\:/, "%3A")
    passage = passage.gsub(/\,/, "%2C")
    get_url @base_url +
             "&passage=#{passage}&#{@options}"
  end
  
  private

  def get_url(url)
    Net::HTTP.get(::URI.parse(url))
  end
end

bible = ESV.new(ARGV[0] || 'IP')

while(true)
  print 'Passage> '
  passage = gets.strip
  unless passage==""
    exit if passage=="exit" || passage=="quit"
    puts bible.doPassageQuery(passage)
  end
end

Python

Thanks to Christian Wyglendowski for this code.

#!/usr/bin/env python

import urllib
import sys

print "Welcome to the ESV Bible passage lookup tool."
print "Enter a passage to view (ex. John 3:16) or 'quit'."

class ESVSession:
    def __init__(self, key):
        options = ['include-short-copyright=0',
                   'output-format=plain-text',
                   'include-passage-horizontal-lines=0',
                   'include-heading-horizontal-lines=0']
        self.options = '&'.join(options)
        self.baseUrl = http://www.esvapi.org/v2/rest/passageQuery?key=%s' % (key)

    def doPassageQuery(self, passage):
        passage = passage.split()
        passage = '+'.join(passage)
        url = self.baseUrl + '&passage=%s&%s' % (passage, self.options)
        page = urllib.urlopen(url)
        return page.read()

try:
    key = sys.argv[1]
except IndexError:
    key = 'IP'

bible = ESVSession(key)

passage = raw_input('Enter Passage: ')
while passage != 'quit':
    print bible.doPassageQuery(passage)
    passage = raw_input('Enter Passage: ')

Also see an OpenOffice plugin written in Python.

XSLT

Ben Edgington has created an XSLT file to convert Crossway's XML to XHTML. You may also want to see his tutorial below.

Blog Plugins

Other Languages

If you would like to contribute simple code for your favorite programming language, we would be happy to post it here.

Tutorials

Demonstrations

The Holy Bible, English Standard Version copyright ©2001 by Crossway Bibles, a publishing ministry of Good News Publishers. Used by permission. All rights reserved.