Twingly Blog Search API v3


Twingly Blog Search API is a commercial XML over HTTP API that enables machine access to Twingly’s blog search index. Currently, the last 12 months of data is searchable through the API. To be able to retrieve data through the API an API key issued by Twingly must be used. The API key then grants access to blog data for one or more languages. If you don’t have access, you can sign up for a free trial.

API Endpoint

A GET request to /search retrieves blog posts which match the specified query. The blog posts are by default returned in date order starting with the newest. At most 1000 hits are returned for a given query.

HTTP options

Request Parameters

Parameter values must be URL encoded.

Parameter Format Example Notes
apikey String E67EFC65-08A9-4086-BE92-074BBD7F78EA Required
q Search query tag:fashion sort:published Required
format String xml Optional, defaults to xml (which is the only allowed value)

Note: The length of the query string may not exceed 2048 characters.

Example query

This will search for all posts with tag “fashion” from the blog, the result will be returned in ascending order by publish date.

tag:fashion sort:published sort-order:asc

See our search language documentation for definitions.

Example Request

With searchpattern: banan page-size:1

curl -s ""


<twinglydata numberOfMatchesReturned="1" secondsElapsed="0.001" numberOfMatchesTotal="114628" incompleteResult="false">
    <title>Oatmeal carrot cake</title>
      Jättegott alternativ till frukost när man har en lite längre morgon! En oatmeal carrot cake, på bara fyra ingredienser! Blanda havregryn, kanel, rivna morötter och mosad banan i en bunke. Tillsätt lite vatten om det behövs, den ska vara hyfsat rinnig. Låt stå på 200 grader en kort stund i ugnen! Smakar precis som en morotskaka!
      <tag>Recept i världsklass</tag>
    <blogName>the mind of jane</blogName>

Elements and attributes:

<twinglydata> is the root element with the following attributes:

Within the root element, <twinglydata>, there can be zero or more <post> elements.

<post> is the root element for a post and contains the following child elements:

Rate limits

We allow for a reasonable amount of concurrent requests, no hard limits. Using the same key for production, staging, and development is also perfectly fine. If you have a need for running lots of queries in parallell for a prolonged time, we’d appreciate if you told us beforehand.


Search responses are cached for 5 minutes, meaning that you will need to wait at least 5 minutes to get fresh results for a given search query. The cache key is the digest of the search pattern and the parameters; if in need to circumvent the cache it is possible to, for instance, change the timestamps slightly.


We strive to respond with the correct HTTP status code and respond with valid XML. But since computers can be tricky at times, you should ensure your client don’t blow up if you get if we give a broken response (please contact us if we do).

The errors from the API looks like this:

<error code="123">

In the GitHub repository for the [Blog Search Ruby client] developed by Twingly, you can find example responses for most errors documented below.

4xx Client errors

Client errors, most likely your client sending invalid requests but please contact us if you can’t figure it out.

HTTP status Error code Description
400 40001 Invalid parameters (see the message for more info)
400 40002 Invalid query (see the message for more info)
400 40003 Invalid query (see the message for more info)
401 40101 Unauthorized
402 40201 Access to language(s) denied (see the message for more info)
404 40401 Not Found

5xx Server errors

HTTP status Error code Description
500 50001 Internal Server Error. Unexpected conditions were encountered, indicating a server-side bug.
503 50301 Service Unavailable. Retry later.

Best practices


If numberOfMatchesTotal is greater than numberOfMatchesReturned, then you will need to paginate through the result in order to retrieve all posts. The best way to do this is to utilize the start-date and/or end-date , creating a sliding time-based window.

Sort with sort-order:asc sort:published Set start-date: to the published time of the newest returned post and repeat your query. Repeat until numberOfMatchesTotal equals numberOfMatchesReturned. This technique can be seen in the examples for the Search API Ruby client.

For the (unusual) case where your search query yields a numberOfMatchesTotal greater than 1,000 (the default page size), where all posts are published at the same time, you can increase numberOfMatchesReturned by adding the page-size option to your search pattern. This works up until the maximum page-size of 10,000. In the very unlikely event that your query still yields more than 10,000 hits you will need to start adding keywords to the query, or add filters such as lang.

Example search pattern with page-size:

"christmas page-size:5000"

If you need to keep the API response small, it’s possible to paginate through up to 10,000 matches, with the page option added to your search pattern. Note that the maximum value for page is 100.

Example search pattern with page and page-size:

"christmas page:2 page-size:100"

Available data

The search index for the Blog Search API contains blog posts from the last 12 months.

As soon as we get new blog content it will be searchable through the Search API. Most often it takes just a few seconds for data to flow through our system, it may be a few minutes during maintenance though.

See also our page about the ingestion system details and challenges.

Search Language

The Twingly search language provides a powerful set of tools to be used when querying the Blog Search API.

Searching for blog posts using keyword

Search all fields for the given keywords.

# search for posts containing the words twingly and blog
twingly blog

# search for posts containing the phrase "I love blogging"
"I love blogging"

# search for posts containing the words twingly or blog
twingly OR blog

# search for posts containing the words twingly and either blog or blogs
twingly AND (blog OR blogs)

# search for posts containing the word twingly but not the word blog
twingly -blog

Searching for Chinese, Japanese and Korean characters

Chinese, Japanese and Korean (CJK) characters are handled as individual words. To search for multi-character words, the word needs to be quoted as a phrase.

# Search for posts containing 東京 (Tokyo).

# Search for posts containing 東 (Eastern) and 京 (Capital).
# For example a post mentioning both "東大" Tokyo University and "京都市" (Kyoto) will match.

Limiting search to a specific field

You can limit the search to specific fields using the following syntax:

# search just the text
fields:text twingly

# search the text and the title
fields:text|title twingly

The supported arguments to fields are:

By default, your search query is matched against all of the fields listed above.

Note that using the fields operator affects the whole query, regardless of parenthesis. For example: (fields:blogname obama) summit would search for “obama” and “summit” only in the blogname field.

Searching for blog posts linking to specific sites

You can search for blog posts that link to specific pages. Note that URLs are normalized in the index, check out the URL normalization section.

# search for posts that link to any page on

# search for posts that link a specific page on

# search for posts that link to any page on *and*,

# search for posts that link to any page on *or*|

# search for posts linking to but not

Note that the link: and -link: operators are computationally expensive. Excessive use of them may slow down the query considerably or even result in a query timeout.

Searching for blog posts on a specific domain

You can search for blog posts on a specific domain, including subdomains. Note that URLs are normalized in the index, check out the URL normalization section.

# search for blog posts on, including

# search for blog posts on several domains|

# search for blog posts mentioning twingly but not on

Note that the site: and -site: operators are computationally expensive. Excessive use of them may slow down the query considerably or even result in a query timeout.

Searching for blog posts on a specific blog

You can search for blog posts on a specific blog. Note that URLs are normalized in the index, check out the URL normalization section.

# search for blog posts on

# search for blog posts on multiple blogs|

# search for blog posts mentioning twingly but not on

Searching for blog posts written in a specific language

You can search for blog posts written in a specific language.

# search for blog posts written in Swedish

# search for blog posts written in Swedish or Finnish

List of all supported languages.

Searching for blog posts from a specific location

You can search for blog posts from a specific location, note that not every post has a location set.

# search for blog posts from Sweden

# search for blog posts from in Sweden or Finland

List of all supported locations.

Searching for blog posts tagged with a specific tag

You can search for blog posts with specific tags.

# search for blog posts with the tag election

# search for blog posts with the tags election *and* obama

# search for blog posts with the tags election, sport *or* fashion

# search for blog posts with the tag obama but not election
tag:obama -tag:election

Searching for blog posts written by a specific author

# search for blog posts with an author named Isabella

# search for blog posts with an author named Isabella but not "Isabella Wight"
author:isabella -author:wight

Searching for a blog post by ID

You can find a specific blog post by using the post id field in the result.


Searching for blog posts within a given time span

The default is to search in posts published at any time.

You can search for posts that were published within the last 24 hours.


The supported arguments to tspan are:

Please note that these are the only supported arguments, e.g. 3h or 4m won’t work

In addition to the tspan parameter you can perform explicit searches on creation (indexed) time or published time.


Timestamps are interpreted as UTC and must be supplied without any time zone information (like shown in the examples above).

Note that using tspan in the same query as start-created, end-created, start-date or end-date is not supported and will yield unexpected results.

Sorting the results

You can sort the blog posts in multiple ways.

# sort by published

# sort by inlinks

The supported arguments to sort are:

Sort order

You can specify the sort order.

# ascending

# descending

Supported languages

To query a specific language, use the the two-letter ISO 639-1 code.

Language Code Remarks
Afrikaans af  
Albanian sq  
Arabic ar  
Bengali bn  
Bulgarian bg  
Catalan ca  
Chinese zh Includes both simplified and traditional Chinese
Croatian hr  
Czech cs  
Danish da  
Dutch nl  
English en  
Estonian et  
Finnish fi  
French fr  
Georgian ka  
German de  
Greek el  
Gujarati gu  
Hebrew he  
Hindi hi  
Hungarian hu  
Icelandic is  
Indonesian id  
Italian it  
Japanese ja  
Kannada kn  
Korean ko  
Lithuanian lt  
Macedonian mk  
Malayalam ml  
Marathi mr  
Nepali ne  
Norwegian no  
Persian fa  
Polish pl  
Portuguese pt  
Punjabi pa  
Romanian ro  
Russian ru  
Serbian sr Only the Cyrillic alphabet is supported
Slovak sk  
Slovenian sl  
Somali so  
Spanish es  
Swahili sw  
Swedish sv  
Tagalog tl  
Tamil ta  
Telugu te  
Thai th  
Turkish tr  
Ukrainian uk  
Urdu ur  
Vietnamese vi  
Welsh cy  

Supported locations

To query a specific location, use the the two-letter ISO 3166-1 alpha-2 format code.

Location Code Remarks
Afghanistan af  
Aland Islands ax  
Albania al  
Algeria dz  
American Samoa as  
Andorra ad  
Angola ao  
Anguilla ai  
Antarctica aq  
Antigua and Barbuda ag  
Argentina ar  
Armenia am  
Aruba aw  
Australia au  
Austria at  
Azerbaijan az  
Bahamas bs  
Bahrain bh  
Bangladesh bd  
Barbados bb  
Belarus by  
Belgium be  
Belize bz  
Benin bj  
Bermuda bm  
Bhutan bt  
Bolivia bo  
Bonaire bq  
Bosnia and Herzegovina ba  
Botswana bw  
Bouvet Island bv  
Brazil br  
British Indian Ocean Territory io  
British Virgin Islands vg  
Brunei Darussalam bn  
Bulgaria bg  
Burkina Faso bf  
Burundi bi  
Cambodia kh  
Cameroon cm  
Canada ca  
Cape Verde cv  
Cayman Islands ky  
Central African Republic cf  
Chad td  
Chile cl  
China cn  
Christmas Island cx  
Cocos cc  
Colombia co  
Comoros km  
Congo cg  
Cook Islands ck  
Costa Rica cr  
Croatia hr  
Cuba cu  
Curacao cw  
Cyprus cy  
Czech Republic cz  
Democratic Peoples Republic of Korea kp  
Democratic Republic of Congo cd  
Denmark dk  
Djibouti dj  
Dominica dm  
Dominican Republic do  
Ecuador ec  
Egypt eg  
ElSalvador sv  
Equatorial Guinea gq  
Eritrea er  
Estonia ee  
Ethiopia et  
Falkland Islands fk  
Faroe Islands fo  
Fiji fj  
Finland fi  
France fr  
French Guiana gf  
French Polynesia pf  
French Southern Territories tf  
Gabon ga  
Gambia gm  
Georgia ge  
Germany de  
Ghana gh  
Gibraltar gi  
Greece gr  
Greenland gl  
Grenada gd  
Guadeloupe gp  
Guam gu  
Guatemala gt  
Guernsey gg  
Guinea Bissau gw  
Guinea gn  
Guyana gy  
Haiti ht  
Heard Island and Mcdonald Islands hm  
Holy See va  
Honduras hn  
Hong Kong hk  
Hungary hu  
Iceland is  
India in  
Indonesia id  
Iran ir  
Iraq iq  
Ireland ie  
Isle of Man im  
Israel il  
Italy it  
Ivory Coast ci  
Jamaica jm  
Japan jp  
Jersey je  
Jordan jo  
Kazakhstan kz  
Kenya ke  
Kiribati ki  
Kuwait kw  
Kyrgyzstan kg  
Lao Peoples Democratic Republic la  
Latvia lv  
Lebanon lb  
Lesotho ls  
Liberia lr  
Libya ly  
Liechtenstein li  
Lithuania lt  
Luxembourg lu  
Macao mo  
Macedonia mk  
Madagascar mg  
Malawi mw  
Malaysia my  
Maldives mv  
Mali ml  
Malta mt  
Marshall Islands mh  
Martinique mq  
Mauritania mr  
Mauritius mu  
Mayotte yt  
Mexico mx  
Micronesia fm  
Moldova md  
Monaco mc  
Mongolia mn  
Montenegro me  
Montserrat ms  
Morocco ma  
Mozambique mz  
Myanmar mm  
Namibia na  
Nauru nr  
Nepal np  
Netherlands nl  
New Caledonia nc  
New Zealand nz  
Nicaragua ni  
Niger ne  
Nigeria ng  
Niue nu  
Norfolk Island nf  
Northern Mariana Islands mp  
Norway no  
Oman om  
Pakistan pk  
Palau pw  
Palestine ps  
Panama pa  
PapuaNewGuinea pg  
Paraguay py  
Peru pe  
Philippines ph  
Pitcairn pn  
Poland pl  
Portugal pt  
PuertoRico pr  
Qatar qa  
Republic of Korea kr  
Reunion re  
Romania ro  
Russian Federation ru  
Rwanda rw  
Saint Barth bl  
Saint Helena sh  
Saint Kitts and Nevis kn  
Saint Lucia lc  
Saint Martin mf  
Saint Pierre and Miquelon pm  
Saint Vincent and the Grenadines vc  
Samoa ws  
SanMarino sm  
Sao Tome and Principe st  
Saudi Arabia sa  
Senegal sn  
Serbia rs  
Seychelles sc  
Sierra Leone sl  
Singapore sg  
Sint Maarten sx  
Slovakia sk  
Slovenia si  
Solomon Islands sb  
Somalia so  
South Africa za  
South Georgia and the South Sandwich Islands gs  
SouthSudan ss  
Spain es  
Sri Lanka lk  
Sudan sd  
Suriname sr  
Svalbard and Jan Mayen sj  
Swaziland sz  
Sweden se  
Switzerland ch  
Syrian Arab Republic sy  
Taiwan tw  
Tajikistan tj  
Tanzania tz  
Thailand th  
Timor tl  
Togo tg  
Tokelau tk  
Tonga to  
Trinidad and Tobago tt  
Tunisia tn  
Turkey tr  
Turkmenistan tm  
Turks and Caicos Islands tc  
Tuvalu tv  
Uganda ug  
Ukraine ua  
United Arab Emirates ae  
United Kingdom gb  
United States Minor Outlying Islands um  
United States us  
Uruguay uy  
US Virgin Islands vi  
Uzbekistan uz  
Vanuatu vu  
Venezuela ve  
Vietnam vn  
Wallis and Futuna wf  
Western Sahara eh  
Yemen ye  
Zambia zm  
Zimbabwe zw  

URL normalization

Since a web resource can have multiple URLs, we apply some normalization to make the index more consistent. However, we do not normalize URLs in link:, blog:, and site: searches automatically. The URL normalization has to be done by the user. Below are some hints on how the URL normalization works.


The scheme part is not taken into account, the original scheme is preserved in the normalized URL.


We add www. for all domains that only consists of a SLD and TLD. ->

For domains with a non-www subdomain, we remove www. if present. ->

Blogger (

Google introduced country specific TLDs for Blogger ( in early 2012. The result of this change is that the same blog will have different URLs (TLDs) dependening on which country you’re currently browsing the web. Consequently, all blogs from Blogger are normalized to, such as:

Known issues

Search timeouts

As the search result property incompleteResult is not yet implemented, it is hard to determine whether the search query was subject to timeouts or not. However, our current search agent timeout is set to 6 seconds. This means that if the secondsElapsed attribute is greater than 6 seconds, then there’s a good chance that at least one search agent timed out – leading to an incomplete result. If this happens repeatedly, consider rewriting your query to a less expensive form.


Changes from previous version

We have focused on simplifying the API request and extending the response.

Changes to output XML:

Migrating from Search v2

Documentation changelog

API changelog