ESV Bible Via REST

March 7th, 2008 by bill · 1 Comment

»A tutorial and demos covering the use of Javascript, jQuery, CSS, and PHP to access, search, and style scripture with the English Standard Version (ESV) REST API.


The ESV Bible REST Web Service

The English Standard Version (ESV) of the Bible is a literal word-for-word translation from Crossway Bibles, who have made it available via a REST web service. There is no charge for non-commercial applications, such as on a personal or church website, though use is limited to 500 verses per query and 5000 queries per day.

The ESV API is a nice rich interface to the Bible. The basic queries include the following:

  • passageQuery – takes a verse reference (or range) and returns the text.
  • query – performs a word search or passage lookup on the search criteria and returns the results.
  • readingPlanQuery – given a date, starting date, and reading plan, such as one-year-tract or chronological, this returns the passage(s) for the date.

There are a lot of options, result formats, etc. so be sure to visit the API page for more details.

Notes On Making This Work

Getting the examples below to work presented some challenges or required some work-arounds or otherwise might be an interesting bit.

Cross-site Ajax requires the use of a proxy. In this case, I’ve got a PHP proxy using Curl to make the actual web service call to the ESV API. The PHP is something along the lines of the following pseudo code:

function geturl($url){
	// typical curl get url code
function request_cache($url, $dest_file, $timeout=604800){
	// Cache code, modified from yahoo developer code
	// Essentially, looks for cached requests and returns them
	//  Otherwise, make the request (then cache it)
$apikey = "IP"; // use your own ESV API key here
// build $cache_fullpath
// build $v cache file name
// init $options to default
foreach ($_GET as $key => $value){
	// find $cmd and build $options key=value string
$url = "$cmd?key=$apikey&$options";
$cache_timeout = 604800; // one week, in seconds
$response = request_cache($url, $cache_fullpath .
	"__" . $v, $cache_timeout);
if ($response === false) {
	die('Request failed');
echo $response;

Caching of requests is also a good idea in this case, and handled by the PHP proxy. This speeds things up a fair bit and reduces load on the ESV API site, but also helps to keep us below the daily request limit of 5000. It’s probably too short, but I’m caching these requests for a week. If you’re interested, I modified some code I found at Yahoo’s developer center. See above for pseudo code integration with PHP proxy.

Embedded link twiddling is accomplished in the some jQuery Javascript embedded in this post. The ESV API takes a link-url parameter that it uses to build links into the query method results, but since I didn’t want to go to the trouble in this example of building a full ESV search facility, I’m pointing the urls back to the ESV site. The code below is part of the success handler for the query .ajax() call. The first line dumps the HTML result into the #esvtext2 div, then the second line executes the inline function for each anchor tag within the results, monkeying with the href.

$("#esvtext2").html( data );
$("#esvtext2 a").each( function(){
	var link = $(this).attr("href");
	$(this).attr("href", link.replace("/esv/search/?",
		"") +
		String.fromCharCode(38) + "key=IP");

Dealing with ampersands in WordPress was causing severe headaches. Their online support insists that encoding them as & or & makes for perfectly wonderful URLs, but the ESV REST API did not agree and simply hated the resultant URLs I was sending its way. That is, until I used String.fromCharCode(38) to inject them into the URL string (see above).

Styling Scripture returned from the API was handled with a CSS style element embedded within this post. One of the things I really appreciate about the ESV API is that the results are so richly-styled. Footnotes (.footnote and .footnotes), chapter and verse numbers (.chapter-num and .verse-num), search results (.search-result), and the words of Christ (.woc) and all easily styled into something that looks pretty decent. (Yes, my CSS is a little junky. Any suggestions are welcome.)

<style type="text/css">
#esvtext1,#esvtext2,#esvtext3 { border:1px solid #ddd; padding:1em; }
.esv * { font-family:Georgia,serif;margin:0;padding:0; }
.esv h2 { font-size:1.3em;margin:0;padding:0; }
.esv h3 { font-size:1.1em;margin:0;padding:0; }
.esv .woc { color:red; }
.esv-text { font-size:1em; }
.esv .search-result{border-top:1px dashed #ccc;}
.esv .search-result-text-heading{font-weight:bold;}
.esv .search-term-1{background-color:#cc9;}
.esv .footnote a{ vertical-align:top;font-size:.8em;color:#777; }
.esv .footnotes { font-size:.8em; }

Scrolling the demos after the Ajax call was complete involved using the scrollTo jQuery plugin and simply doing a $.scrollTo( “#demo1”, 500 ) in the Ajax success handler, after sticking the results in the demo results div. This scrolls the corresponding demo intro to the top of the page. Nice.

        $("#esvtext1").html( data );
        $.scrollTo( "#demo1", 500 );

Cleaning up results of previous requests is accomplished with an easy jQuery line. In the success handler for each Ajax call, the first thing that happens is setting the results div for each of the other two demos to an empty string. The code above is the Ajax success handler for the first demo.


The examples below are three forms and an empty div. The three forms are bound to some jQuery (of course), which submits Ajax requests to a PHP proxy, then sticks the results in the empty div. For search results, embedded relative links are changed to point to the ESV site.

Demo 1: passageQuery

The sample below simply requests the passage from the ESV REST interface via the PHP proxy and pops the results into the results div. In the absence of specifying otherwise, we get it back in default format (HTML) with default options. The basic format for a passage is Book Verse:Chapter, but the API supports multiple passages, such as John 14:1-10,gen 1,is 2.

Verse: (ex: John 14:1-10)


Demo 2: query

The sample below is similar to the passageQuery except that you can send either a passage or a query word such as Messiah or fisher and get back the results. Paging is supported by the API (though not in this demo), so if the results span multiple pages you can request arbitrary pages as well (page=3, etc.). Other available options include sending your own search URL base for embedded links, number of results per page, and more.

Search terms: (ex: John 14:1-10, or samaritan, or dragon)


Demo 3: readingPlanQuery

The readingPlanQuery sample simply allows you to select from a few different plans and sends the request. The default date is today, and the default start date is January 1st, so we’ll just use those.



Tags: Programming


1 response so far ↓

  • 1 Hamish Erskine // Jun 3, 2009 at 8:32 am

    I am wanting to just call the BCP reading plan for a page on Joomla, and I’ve got directphp installed. I’ve tried all the options on the API but still am having trouble.

    From you’re pseudo-code, is there anything I’m missing?

Leave a Comment

eight − = 7