Understanding the Solr JSON Response

Documentation > WEB CRAWLER-Solr API > Understanding the Solr JSON Response

Understanding the Solr JSON Response

When you query your Opensolr Web Crawler index via the /select API, you get back a JSON object. This page explains every section of that response so you know exactly how to parse it in your application.


The Basic Response Structure

Here is a simplified example of what comes back when you search:

{
  "responseHeader": {
    "status": 0,
    "QTime": 12
  },
  "response": {
    "numFound": 1542,
    "start": 0,
    "numFoundExact": true,
    "docs": [
      { ... },
      { ... }
    ]
  },
  "highlighting": {
    "doc_id_1": { ... },
    "doc_id_2": { ... }
  },
  "facet_counts": {
    "facet_fields": { ... }
  },
  "spellcheck": {
    "suggestions": [ ... ],
    "collations": [ ... ]
  }
}

responseHeader

"responseHeader": {
  "status": 0,
  "QTime": 12
}
Field Description
status 0 means success. Any other value means an error occurred.
QTime Query execution time in milliseconds. This is how long Solr took to process your query (not including network time). A good search returns in under 50ms.

response

This is the main section containing your search results.

"response": {
  "numFound": 1542,
  "start": 0,
  "numFoundExact": true,
  "docs": [ ... ]
}
Field Description
numFound Total number of documents matching your query. This is the number you display as "Showing results 1-10 of 1,542".
start The offset you requested (from the start parameter).
numFoundExact Whether numFound is exact (true) or an approximation. Almost always true.
docs Array of document objects — your actual search results.

A Document Object

Each item in the docs array looks like this:

{
  "id": "bc434cee9e50b48f80095c9f49bdeae3",
  "uri": "https://yoursite.com/blog/my-article",
  "title": "My Article Title",
  "description": "A short description of the article...",
  "text": "The full body text of the page...",
  "og_image": "https://yoursite.com/images/article-thumb.jpg",
  "meta_icon": "https://yoursite.com/favicon.ico",
  "meta_domain": "yoursite.com",
  "meta_detected_language": "en",
  "content_type": "text/html",
  "creation_date": "2026-02-20T14:30:00Z",
  "timestamp": 1771684200,
  "sent_pos": 0.153,
  "sent_neu": 0.752,
  "sent_neg": 0.095,
  "sent_com": 0.9856,
  "score": 1.8234,
  "price_f": 29.99,
  "currency_s": "USD"
}

The fields you get back depend on what you specified in the fl (field list) parameter. The score field is special — it is computed at query time and represents the relevancy score for that document.

Tip: Only request the fields you actually need. Requesting text (full body text) for every result increases response size significantly. If you only display titles and snippets, use fl=id,uri,title,description,og_image,score.


highlighting

If you set hl=true in your query, you get a highlighting section keyed by document ID:

"highlighting": {
  "bc434cee9e50b48f80095c9f49bdeae3": {
    "title": ["My <em>Article</em> Title"],
    "description": ["A short description about <em>article</em> writing..."],
    "text": ["...the main body discusses <em>article</em> formatting and..."]
  },
  "another_doc_id": {
    "title": ["Another <em>Article</em>"]
  }
}

How to use it in your code:

  1. Loop through your docs array
  2. For each doc, look up highlighting[doc.id]
  3. If a highlighted version exists for a field, use it instead of the raw field value
  4. The <em> tags wrap the matching search terms — style them with CSS (bold, background color, etc.)
// Example: get the best title to display
var docId = doc.id;
var hl = data.highlighting[docId] || {};
var displayTitle = (hl.title && hl.title[0]) ? hl.title[0] : doc.title;

Important: Highlighted text contains HTML (<em> tags), so you should insert it using innerHTML, not textContent. The rest of the text is already HTML-escaped by Solr.


facet_counts

If you set facet=true, you get a facet_counts section:

"facet_counts": {
  "facet_fields": {
    "meta_detected_language": [
      "en", 834,
      "de", 245,
      "fr", 123,
      "es", 89,
      "nl", 42
    ],
    "currency_s": [
      "USD", 156,
      "EUR", 89
    ]
  }
}

The facet arrays alternate between value and count: ["en", 834, "de", 245, ...] means 834 results in English, 245 in German, etc.

Parsing facets in JavaScript:

var langFacets = data.facet_counts.facet_fields.meta_detected_language;
var facets = [];
for (var i = 0; i < langFacets.length; i += 2) {
    facets.push({ value: langFacets[i], count: langFacets[i+1] });
}
// facets = [{value: "en", count: 834}, {value: "de", count: 245}, ...]

You can then render these as clickable filter buttons or a sidebar. When the user clicks "English (834)", add fq=meta_detected_language:en to your query to filter.


spellcheck

If you enabled spellcheck, you get suggestions for misspelled words:

"spellcheck": {
  "suggestions": [
    "opnesolr", {
      "numFound": 1,
      "suggestion": ["opensolr"]
    }
  ],
  "collations": [
    "collation", "opensolr search"
  ]
}

The collations section is the most useful — it gives you a corrected version of the entire query that you can show as "Did you mean: opensolr search?".

Parsing collations:

var collations = data.spellcheck ? data.spellcheck.collations : [];
if (collations.length >= 2) {
    var suggestion = collations[1]; // The corrected query string
    // Display: "Did you mean: <a>suggestion</a>?"
}

Error Responses

If something goes wrong, the response looks like this:

{
  "responseHeader": {
    "status": 400
  },
  "error": {
    "msg": "undefined field: nonexistent_field",
    "code": 400
  }
}

Always check responseHeader.status — if it is not 0, read the error.msg for details. Common errors:

  • 400 — Bad query syntax, undefined field, or invalid parameter value
  • 500 — Server error (rare, usually a misconfigured query)

stats

If you requested stats on a numeric field (e.g., stats=true&stats.field=price_f):

"stats": {
  "stats_fields": {
    "price_f": {
      "min": 4.99,
      "max": 299.99,
      "count": 156,
      "missing": 1386,
      "sum": 12450.50,
      "mean": 79.81
    }
  }
}

This is useful for displaying price ranges or other numeric summaries in your UI.