IIIF Examples #1: Wellcome Library

Published: 2016-10-01 23:13 -0400

As I’m improving the implementation of IIIF on the NCSU Libraries Rare and Unique Digital Collections site, I’m always looking for examples from other implementations for how they’re implementing various features. This will mostly be around the Presentation and Content Search APIs where there could be some variability.

This is just a snapshot look at some features for one resource on the Wellcome Library site, the example may not be good or correct, and could be changed by the time that you read this. I’m also thinking out loud here and asking lots of questions about my own gaps in knowledge and understanding. In any case I hope this might be helpful to others.


The example I’m looking at is the “[Report of the Medical Officer of Health for Wandsworth District, The Board of Works (Clapham, Putney, Streatham, Tooting & Wandsworth)]”. You ought to be able to see the resource an embedded view below with UniversalViewer:

If you visit the native page and scroll down it you’ll see some some other information. They’ve taken some care to expose tables within the text and show snippets of those tables. This is a really nice example of how older texts might be able to be used in new research. And even though Universal Viewer provides some download options they provide a separate download option for the tables. Clicking on one of the tables displays the full table. Are they using OCR to extract tables? How do they recognize tables and then ensure that the text is correct?

Otherwise the page includes the barest amount of metadata and the “more information” panel in UV does not provide much more.

This collection includes a good page with more information about these medical reports including a page about how to download and use the report data.

Presentation API

I’m now going to go down and read through sections of the presentation manifest for this resource and note what I find interesting.

The manifest links back to the HTML page with a related property at the top level like this:

"related": {
  "@id": "http://wellcomelibrary.org/item/b18250464",
  "format": "text/html"

There has been some discussion where the right place is to put a link back from the manifest to an HTML page for humans to see the resource. The related property may not be the right one and that YKK should be used instead.


The manifest has a seeAlso for an RDF (turtle) representation of the resource:

"seeAlso": {
  "@id": "http://wellcomelibrary.org/resource/b18250464",
  "format": "text/turtle"

What other types of seeAlso links are different manifests providing?


Several different services are given. Included are standard services for Content Search and autocomplete. (I’ll come back to to those in a bit.) There are also a couple services outside of the iiif.io context.

The first is an extension around access control. Looking at the context you can see different levels of access shown–open, clickthrough, credentials. Not having looked closely at the Authentication specification, I don’t know yet whether these are aligned with that or not. The other URLs here don’t resolve to anything so I’m not certain what their purpose is.

  "@context": "http://wellcomelibrary.org/ld/iiif-ext/0/context.json",
  "@id": "http://wellcomelibrary.org/iiif/b18250464-0/access-control-hints-service",
  "profile": "http://wellcomelibrary.org/ld/iiif-ext/access-control-hints",
  "accessHint": "open"

There’s also a service that appears to be around analytics tracking. From the context document http://universalviewer.io/context.json it appears that there are other directives that can be given to UV to turn off/on different features. I don’t remember seeing anything in the UV documentation on the purpose and use of these though.


One thing I’m interested in is how organizations name and give ids (usually HTTP URLs) for resources that require them. In this case the id of the only sequence is a URL that ends in “/s0” and resolves to an error page. The label for the sequence is “Sequence s0” which could have been automatically generated when the manifest was created. This lack of an id and label value for a sequence is understandable since these types of things wouldn’t regularly get named in a metata workflow or

This leaves me with the question of which ids ought to have something at the other end of the URI? Should every URI give you something useful back? And is there the assumption that HTTP URIs ought to be used rather than other types of identifiers–ones that might not have the same assumptions about following them to something useful? Or are these URIs just placeholders for good intentions of making something available there later on?


Both PDF and raw text renderings are made available. It was examples like this one that helped me to see where to place renderings so that UniversalViewer would display them in the download dialog. The PDF is oddly extensionless, but it does work and it has a nice cover page that includes a persistent URL and a statement on conditions of use. The raw text would be suitable for indexing the resource, but is one long string of text without break so not really for reading.


The viewingHint given here is “paged.” I’ll admit that one of the more puzzling things to me about the specification is exactly what viewing experience is being hinted at with the different viewing hints. How do each of these effect, or not, different viewers? Are there examples of what folks expect to see with each of the different viewing hints?


The canvases don’t dereference and seem to follow the same sort of pattern as sequences by adding “/canvas/c0” to the end of an identifier. There’s a seeAlso that points to OCR as ALTO XML. Making this OCR data available with all of the details of bounding boxes of lines and words on the text is potentially valuable. The unfortunate piece that there’s no MIME type for ALTO XML so the format here is generic and does not unambiguously indicate that the type of file will contain ALTA OCR.

"seeAlso": {
  "@id": "http://wellcomelibrary.org/service/alto/b18250464/0?image=0",
  "format": "text/xml",
  "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd",
  "label": "METS-ALTO XML"

Even more interesting for each canvas they deliver otherContent that includes an annotation list of the text of the page. Each line of the text is a separate annotation, and each annotation points to the relevant canvas including bounding boxes. Since the annotation list is on the canvas the on property for each annotation has the same URL except for a different fragment hash for the bounding box for the line. I wonder if there is code for extracting annotation lists like this from ALTO? Currently each annotation is not separately dereferenceable and uses a similar approach as seen with sequences and canvases of incrementing a number on the end of the URL to distinguish them.

In looking closer at the images on the canvas, I learned better about how to think about the width/height of the canvas as opposed to the width/height of the image resource and what the various ids within a canvas, image, and resource ought to mean. I’m getting two important bits wrong currently. The id for the image should be to the image as an annotation and not to the image API service. Similarly the id for the image resource ought to actually be an image (with format given) and again not the URL to the image API. For this reason the dimensions of the canvas can be different (and in many cases larger) than the dimensions of the single image resource given as it can be expensive to load very large images.

Content Search API

Both content search and autocomplete are provided for this resource. Both provide a simple URL structure where you can just add “?q=SOMETHING” to the end and get a useful response.


First thing I noticed about the content search response is that it is delivered as “text/plain” rather that JSON or JSON-LD, which is something I’ll let them know about. Otherwise this looks like a nice implementation. The hits include both the before and after text which could be useful for highlighting the text off of the canvas.

The annotations themselves use ids that include the the bounding box as a way to distinguish between them. Again they’re fine identifiers but do don’t have anything at the other end. So here’s an example annotation where “1697,403,230,19” is used for both the media fragment as well as the annotation URL:

  "@id": "http://wellcomelibrary.org/iiif/b18250464/annos/searchResults/a80h40r1697,403,230,19",
  "@type": "oa:Annotation",
  "motivation": "sc:painting",
  "resource": {
    "@type": "cnt:ContentAsText",
    "chars": "Medical"
  "on": "http://wellcomelibrary.org/iiif/b18250464/canvas/c80#xywh=1697,403,230,19"

The autocomplete service is simple enough: http://wellcomelibrary.org/annoservices/autocomplete/b18250464?q=med


I learned a bit about how ids are used in this implementation. I hope this helps give some pointers to where others can learn from the existing implementations in the wild.