The Holy Bible, English Standard Version

Using the ESV Bible as a Web Service - API

Show me a general introduction...

What's New

Because this service is still in beta, this API is subject to change without notice. In the examples below, the testing key is used, which scrambles the text. When you have an access key, the text appears normally.

HTTP-GET Interface

The base url for all GET requests is: http://www.gnpcb.org/esv/share/get/

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

For doPassageQuery:

 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).
action Set to doPassageQuery (look up a passage).

For doQuery:

 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.
action Set to doQuery (look up a passage or show word-search results, depending on the query).

For doReadingPlanQuery:

 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.
action Set to doReadingPlanQuery (retrieve passages from our Devotions section. More...).

For getQueryInfo:

 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.
action Set to getQueryInfo (parse and display information about your query, including identify whether it is a passage reference or a word search. More...).

For getReadingPlanInfo:

 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.
action Set to getReadingPlanInfo (parse and display information about the reading plan for a given date. More...).

For getVerse:

 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.
action Set to getVerse (display a random verse from a preselected list, or specify verse(s). More...).

For getDailyVerse:

 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.
action Set to getDailyVerse (display a verse that changes every day. More...).

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

Sample Queries using the testing key (scrambled output)

SOAP Interface

The SOAP interface should be considered experimental. We've tested it with Perl's SOAP::Lite module and PHP's NuSOAP. It does not always return SOAP faults correctly (for example, if you execute doQuery without an options argument).

The base url for all SOAP requests is http://www.gnpcb.org/esv/share/soap/

We suggest a namespace of http://www.crosswaybibles.org/soap

Currently, the available functions are:

  1. doPassageQuery, which takes the following inputs:
    • Parameter 1: $key. Your access key.
    • Parameter 2: $passage. The passage(s) you want to look up.
    • Parameter 3: $options. Optional. An associative array containing any of the options listed below. The available options depend on your desired output format.
  2. doQuery, which returns search results or a passage depending on the query. It takes the following inputs:
    • Parameter 1: $key. Your access key.
    • Parameter 2: $options. An associative array containing any of the options listed below. It must contain at least one of the following keys: q, passage, words, phrase. More about doQuery...
  3. doReadingPlanQuery, which shows passages corresoponding to a reading plan. It takes the following inputs:
    • Parameter 1: $key. Your access key.
    • Parameter 2: $options. Optional. An associative array containing any of the options listed below. As with doPassageQuery, the available options depend on your desired output format. More about doReadingPlanQuery...
  4. getQueryInfo, which parses your query and gives you information about it. It takes the following inputs:
  5. getVerse, which resembles doPassageQuery except it corrects beginning punctuation and matches quotes. It takes the following inputs:
    • Parameter 1: $key. Your access key.
    • Parameter 2: $options. Optional. An associative array containing any of the options described in getVerse below, including a passage reference. It can also contain any output formatting options.
  6. getDailyVerse, which is identical to getVerse except that it shows the same verse for a span of one day, making it suitable for verse-of-the-day applications. It takes the following inputs:
    • Parameter 1: $key. Your access key.
    • Parameter 2: $options. Optional. An associative array containing any of the options described in getDailyVerse below. It can also contain any output formatting options.

WSDL

Technical documentation and a WSDL file are also available.

Sample Queries (the exact format depends on the language you're using. These are in Perl)

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-first-verse-numbers true Show the verse number (e.g., 53:1) at the beginnings of chapters.
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 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 real Takes a value of flash, mp3, real, or wma to indicate the format of the audio. It defaults to real for historical reasons, but the default could change (to flash); 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. The mp3 option includes a link to an M3U file. However, this link expires after about 24 hours, making it unsuitable for extended caching. 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 mm Which recording to use. The options are: mm (Max McLean, complete Bible), ml (Marquis Laughlin, New Testament only), and ml-mm (Max McLean for Old Testament, Marquis Laughlin for New Testament. Only affects the output if audio-format is flash or mp3. (Max McLean's version is 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.

The following options all 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

Function doQuery

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 doPassageQuery.
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 doReadingPlanQuery

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 (e.g., 2008-05-09 for today). The date changes at midnight US Eastern Time (GMT -0500).
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.

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

Function getQueryInfo

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.

See a demonstration of a possible use with the Bible Gateway.

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>
   <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.
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 getReadingPlanInfo

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., 2008-05-09 for today). The date changes at midnight US Eastern Time (GMT -0500).
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 getVerse

This function resembles doPassageQuery, except the additional formatting options described in getDailyVerse 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, getDailyVerse simply calls this function using the current date as the seed.)

For example, the following url:

http://www.gnpcb.org/esv/share/get/?key=TEST&action=getVerse&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 getDailyVerse

This argument retrieves a verse at random from the verses we've collected. The verse rolls over at midnight U.S. Eastern Time (GMT -5 or -4). 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

GET

use LWP::Simple;
my $key = "IP";
my $passage = "Matthew 5";
my $options = "action=doPassageQuery&include-verse-numbers=false";
my $output = get("http://www.gnpcb.org/esv/share/get/?key=$key&passage=$passage&$options");
print $output;

SOAP

use SOAP::Lite;
my $key = "IP";
my $passage = "Matthew 5";
my $options = {
		"include-quote-entities" => 1,
		"output-format" => "plain-text",
		};
print SOAP::Lite
    -> uri('http://www.crosswaybibles.org/soap')
    -> proxy('http://www.gnpcb.org/esv/share/soap/')
    -> doPassageQuery($key, $passage, $options)
    -> result;

SOAP (using WSDL file)

use SOAP::Lite;
my $key = "IP";
my $options = {
    "q" => "Elijah",
    };
print SOAP::Lite
    -> service('http://www.gnpcb.org/esv/share/soap/?wsdl')
    -> doQuery($key, $options)
    -> result;

PHP

GET

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

<?php
  $key = "IP";
  $passage = urlencode("john 3:16");
  $options = "action=doPassageQuery&include-passage-references=false";
  $url = "http://www.gnpcb.org/esv/share/get/?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 = "action=doPassageQuery&include-passage-references=false&audio-format=flash";
  $url = "http://www.gnpcb.org/esv/share/get/?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");
  }
?>

SOAP (using NuSOAP)

Thanks to Ben Edgington for this code.

<?php
require_once('nusoap.php');
$server = 'http://www.gnpcb.org/esv/share/soap/';
$soapclient = new soapclient($server);
$options = array(
    'output-format'=>'html',
    'include-footnotes' => false,
    );
$parameters = array(
    'key' => 'IP',
    'passage' => 'Rom 8',
    'options' => $options);

$result = $soapclient->call('doPassageQuery', $parameters);
print $result;
?>

SOAP (using NuSOAP and WSDL file)

<?php
require_once('nusoap.php');
$soapclient = new soapclient('http://www.gnpcb.org/esv/share/soap/?wsdl', true);
$parameters = array(
    'key' => 'IP',
    'options' => array(
        'output-format' => 'plain-text',
        'include-short-copyright' => false,
        'include-passage-horizontal-lines' => false,
        'include-section-horizontal-lines' => false,
        'include-verse-numbers' => false,
       ),
    );
print $soapclient->call('getDailyVerse', $parameters);
?>

VB.NET

GET

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

Dim strURL as New StringBuilder()
With strURL
    .Append("http://www.gnpcb.org/esv/share/get/")
    .Append("?key=IP")
    .Append("&passage=" & Server.URLEncode("Matthew 5"))
    .Append("&action=doPassageQuery")
    .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#

GET

StringBuilder sUrl = new StringBuilder();
sUrl.Append("http://www.gnpcb.org/esv/share/get/");
sUrl.Append("?key=IP");
sUrl.Append("&passage=" + Server.UrlEncode("Matthew 5").ToString());
sUrl.Append("&action=doPassageQuery");
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

GET

Thanks to Simon Job for this code.

<%
  'Reference Search
  key = "IP"
  strSearch = "John 1"
  passage = Server.URLEncode(strSearch)
  options = "action=doPassageQuery&include-passage-references=true"
  set objHTTP = Server.CreateObject("Microsoft.XMLHTTP")
  objHTTP.open "GET", "http://www.gnpcb.org/esv/share/get/?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

GET

Thanks to David Scarbrough for this code.

<cfset key = "IP">
<cfset passage = "2 Tim 3:16">
<cfset options = "action=doPassageQuery&include-verse-numbers=false">
<cfhttp
  url = "http://www.gnpcb.org/esv/share/get/?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.gnpcb.org/esv/share/get/");
    urlStringBuilder.append("?key=IP");
    urlStringBuilder.append("&passage="
        + URLEncoder.encode(book + " " + chapter, "ISO-8859-1"));
    urlStringBuilder.append("&action=doPassageQuery");
    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.gnpcb.org/esv/share/get/");
    urlStringBuffer.append("?key=IP");
    urlStringBuffer.append(
      "&passage=" + URLEncoder.encode(book + " " + chapter));
    urlStringBuffer.append("&action=doPassageQuery");
    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.gnpcb.org/esv/share/get/?key=#{key}"
  end

  def doPassageQuery(passage)
    passage = passage.gsub(/\s/, "+")
    passage = passage.gsub(/\:/, "%3A")
    passage = passage.gsub(/\,/, "%2C")
    get_url @base_url +
             "&passage=#{passage}&action=doPassageQuery&#{@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.gnpcb.org/esv/share/get/?key=%s' % (key)

    def doPassageQuery(self, passage):
        passage = passage.split()
        passage = '+'.join(passage)
        url = self.baseUrl + '&passage=%s&action=doPassageQuery&%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

Gospelcom.net Alliance Member