How do I get info about a Youtube video's chapters from the API? - api

Recently, Youtube added the ability to break up their videos in the progress bar into sections called "chapters".
https://support.google.com/youtube/answer/9884579?hl=en
Currently I am able to get info about a video from the Youtube API. However, it doesn't seem like there's any info about a video's chapters, and I haven't found anything in the API documentation about chapters. Am I missing something, or is there simply no way to get chapter data yet?

As far as I know, such data is in plain text in the description of the video.
So, you can use the following example:
Video used in this demonstration: Top 10 Monsters with 2500 Attack in YuGiOh
URL Request:
https://www.googleapis.com/youtube/v3/videos?part=snippet&id=NNgYId7b4j0&key=[YOUR_API_KEY]
Response:
{
"kind": "youtube#videoListResponse",
"etag": "YpVLmrSx1iP8hAJOnumaTBoKqqQ",
"items": [
{
"kind": "youtube#video",
"etag": "oIoJq5F3RHvBbtVohafaJ_1SThU",
"id": "NNgYId7b4j0",
"snippet": {
"publishedAt": "2020-09-14T18:37:46Z",
"channelId": "UC0roOaAn95Rtgoe078RkVXQ",
"title": "Top 10 Monsters with 2500 Attack in YuGiOh",
"description": "In this video we'll go over the best monsters that have 2500 attack, and attack threshold for a lot of boss monsters actually.\n\nCheck out my DnD channel #TheD&DLogs \n\n--The List--\nIntro: (0:00)\n10- Blue-Eyes Spirit Dragon: (0:00)\n9- Invoked Mechaba: (2:14)\n8- Number S39: Utopia the Lightning: (3:23)\n7- Earthbound Immortal Aslla Piscu: (4:35)\n6- Eldlich the golden Lord: (6:04)\n5- True King Lithosagym the Disaster: (7:34)\n4- Block Dragon: (8:54)\n3- Astrograph sorcerer: (10:25)\n2- Beatrice lady of the eternal: (12:36)\n1- Firewall Dragon: (14:37)\n- \n-----------------------------------------\n#yugioh #top10 \n\nDuels are all done on EDOpro, its completely free and updated all the time. If you want it, just look for the EDOpro discord and you'll find all you need to download it from there\n\nSome of the Video backgrounds in this video were made by \"Amitai Angor AA VFX\" https://www.youtube.com/dvdangor2011\n\n\nhttps://twitter.com/hirumared\nhttps://twitter.com/TheDuelLogs",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/NNgYId7b4j0/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/NNgYId7b4j0/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/NNgYId7b4j0/hqdefault.jpg",
"width": 480,
"height": 360
},
"standard": {
"url": "https://i.ytimg.com/vi/NNgYId7b4j0/sddefault.jpg",
"width": 640,
"height": 480
},
"maxres": {
"url": "https://i.ytimg.com/vi/NNgYId7b4j0/maxresdefault.jpg",
"width": 1280,
"height": 720
}
},
"channelTitle": "TheDuelLogs",
"tags": [
"yugioh",
"ygo",
"dev",
"pro",
"link",
"duels",
"auto-matic duels",
"online",
"current",
"ban",
"list",
"dueling",
"network",
"theduellogs",
"the",
"duel",
"logs",
"loggs",
"Yu",
"Gi",
"Oh!",
"YGOpro",
"gimmick",
"links",
"top ten",
"2020",
"edopro"
],
"categoryId": "20",
"liveBroadcastContent": "none",
"localized": {
"title": "Top 10 Monsters with 2500 Attack in YuGiOh",
"description": "In this video we'll go over the best monsters that have 2500 attack, and attack threshold for a lot of boss monsters actually.\n\nCheck out my DnD channel #TheD&DLogs \n\n--The List--\nIntro: (0:00)\n10- Blue-Eyes Spirit Dragon: (0:00)\n9- Invoked Mechaba: (2:14)\n8- Number S39: Utopia the Lightning: (3:23)\n7- Earthbound Immortal Aslla Piscu: (4:35)\n6- Eldlich the golden Lord: (6:04)\n5- True King Lithosagym the Disaster: (7:34)\n4- Block Dragon: (8:54)\n3- Astrograph sorcerer: (10:25)\n2- Beatrice lady of the eternal: (12:36)\n1- Firewall Dragon: (14:37)\n- \n-----------------------------------------\n#yugioh #top10 \n\nDuels are all done on EDOpro, its completely free and updated all the time. If you want it, just look for the EDOpro discord and you'll find all you need to download it from there\n\nSome of the Video backgrounds in this video were made by \"Amitai Angor AA VFX\" https://www.youtube.com/dvdangor2011\n\n\nhttps://twitter.com/hirumared\nhttps://twitter.com/TheDuelLogs"
},
"defaultAudioLanguage": "en"
}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
Get the response:
response.items[0].snippet.description
Results:
"In this video we'll go over the best monsters that have 2500 attack, and attack threshold for a lot of boss monsters actually.
Check out my DnD channel #TheD&DLogs
--The List--
Intro: (0:00)
10- Blue-Eyes Spirit Dragon: (0:00)
9- Invoked Mechaba: (2:14)
8- Number S39: Utopia the Lightning: (3:23)
7- Earthbound Immortal Aslla Piscu: (4:35)
6- Eldlich the golden Lord: (6:04)
5- True King Lithosagym the Disaster: (7:34)
4- Block Dragon: (8:54)
3- Astrograph sorcerer: (10:25)
2- Beatrice lady of the eternal: (12:36)
1- Firewall Dragon: (14:37)
-
-----------------------------------------
#yugioh #top10
Duels are all done on EDOpro, its completely free and updated all the time. If you want it, just look for the EDOpro discord and you'll find all you need to download it from there
Some of the Video backgrounds in this video were made by "Amitai Angor AA VFX" https://www.youtube.com/dvdangor2011
https://twitter.com/hirumared
https://twitter.com/TheDuelLogs"

One more time YouTube Data API v3 doesn't provide a basic feature.
I would suggest you to use my open-source YouTube operational API, indeed by requesting https://yt.lemnoslife.com/videos?part=chapters&id=VIDEO_ID you would get a JSON with the video chapters (titles and timestamps) you are looking for in item['chapters']['chapters'].
Example of result with YouTube video id NNgYId7b4j0:
{
"kind": "youtube#videoListResponse",
"etag": "NotImplemented",
"items": [
{
"kind": "youtube#video",
"etag": "NotImplemented",
"id": "NNgYId7b4j0",
"chapters": {
"areAutoGenerated": false,
"chapters": [
{
"title": "10- Blue-Eyes Spirit Dragon",
"time": 0,
"thumbnails": [
{
"url": "https:\/\/i.ytimg.com\/vi\/NNgYId7b4j0\/hqdefault_4000.jpg?sqp=-oaymwEiCKgBEF5IWvKriqkDFQgBFQAAAAAYASUAAMhCPQCAokN4AQ==&rs=AOn4CLCoTrvu0Yu-iNxb7o4II-pxi5WVbQ",
"width": 168,
"height": 94
},
{
"url": "https:\/\/i.ytimg.com\/vi\/NNgYId7b4j0\/hqdefault_4000.jpg?sqp=-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE=&rs=AOn4CLCuupNwIgFIf9hXbjMsvpSGThFyhg",
"width": 336,
"height": 188
}
]
},
{
"title": "9- Invoked Mechaba",
"time": 134,
"thumbnails": [
{
"url": "https:\/\/i.ytimg.com\/vi\/NNgYId7b4j0\/hqdefault_135933.jpg?sqp=-oaymwEiCKgBEF5IWvKriqkDFQgBFQAAAAAYASUAAMhCPQCAokN4AQ==&rs=AOn4CLBe94BKNpQXvM2dUl75LtcgX0N03w",
"width": 168,
"height": 94
},
{
"url": "https:\/\/i.ytimg.com\/vi\/NNgYId7b4j0\/hqdefault_135933.jpg?sqp=-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE=&rs=AOn4CLBULUhlI1OOjJiW6mpFDUhPzh4Adw",
"width": 336,
"height": 188
}
]
},
...
]
}
}
]
}

I am replying with this answer to help people such as myself who ended up on this video wanting to find a youtube chapter parser / extractor for text rather than where to find the chapter data. Just to add some further information, currently, there is no way to get the chapters from the official YouTube API, so the only way to get the chapters from a text-description response (like the YouTube API provides) is to parse it in some way:
My answer is in Javascript but it can easily be converted: The idea is to extract the MIN:SEC and HR:MIN:SEC timestamps then to generate the title we remove the word that includes them (So this would typically remove however people aesthetically wrap them too [00:00] or (00:00)
It's far from perfect, but in my experience it's better than the other solutions I've seen on github/npm at the time of writing this. You might want to also trim away starting and ending spaces and punctuational separators such as (-, :, ~, |) too
const parseChapters = (description) => {
// Extract timestamps (either 00:00:00, 0:00:00, 00:00 or 0:00)
const lines = description.split("\n")
const regex = /(\d{0,2}:?\d{1,2}:\d{2})/g
const chapters = []
for (const line of lines) {
// Match the regex and check if the line contains a matched regex
const matches = line.match(regex)
if (matches) {
const ts = matches[0]
const title = line
.split(" ")
.filter((l) => !l.includes(ts))
.join(" ")
chapters.push({
timestamp: ts,
title: title,
})
}
}
return chapters
}

Very late answer but it solved my problem.
You could use the code below. It's written in C# but it can easily be transcribed into another language. Since you can already get youtube video data, I assume you also have the description of the video.
private static IEnumerable<string> GetChaptersFromDescription(string text)
{
var lines = text.Split("\n");
var regex = new Regex(#"[0-9]:[0-9][0-9]");
foreach (var line in lines)
{
if (regex.IsMatch(line))
{
yield return line;
}
}
}

Related

How to get new Search Engine results in the past 24h using a SERP API?

Assume I am in possession of a SERP API, which given a keyword, returns me the Google results of that keyword in JSON format (for example: https://serpapi.com/):
{
"organic_results": [
{
"position": 1,
"title": "Coffee - Wikipedia",
"link": "https://en.wikipedia.org/wiki/Coffee",
"displayed_link": "https://en.wikipedia.org › wiki › Coffee",
"snippet": "Coffee is a brewed drink prepared from roasted coffee beans, the seeds of berries from certain Coffea species. From the coffee fruit, the seeds are ...",
"sitelinks":{/*snip*/}
,
"rich_snippet":
{
"bottom":
{
"extensions":
[
"Region of origin: Horn of Africa and ‎South Ara...‎",
"Color: Black, dark brown, light brown, beige",
"Introduced: 15th century"
]
,
"detected_extensions":
{
"introduced_th_century": 15
}
}
}
,
"about_this_result":
{
"source":
{
"description": "Wikipedia is a free content, multilingual online encyclopedia written and maintained by a community of volunteers through a model of open collaboration, using a wiki-based editing system. Individual contributors, also called editors, are known as Wikipedians.",
"source_info_link": "https://en.wikipedia.org/wiki/Wikipedia",
"security": "secure",
"icon": "https://serpapi.com/searches/6165916694c6c7025deef5ab/images/ed8bda76b255c4dc4634911fb134de53068293b1c92f91967eef45285098b61516f2cf8b6f353fb18774013a1039b1fb.png"
}
,
"keywords":
[
"coffee"
]
,
"languages":
[
"English"
]
,
"regions":
[
"the United States"
]
}
,
"cached_page_link": "https://webcache.googleusercontent.com/search?q=cache:U6oJMnF-eeUJ:https://en.wikipedia.org/wiki/Coffee+&cd=4&hl=en&ct=clnk&gl=us",
"related_pages_link": "https://www.google.com/search?q=related:https://en.wikipedia.org/wiki/Coffee+Coffee"
},
/* Results 2,3,4... */
]}
What is a good way to get new results from the past 24h? I added the &tbs=qdr:d query parameter, which only shows the results from the past day. That's a good first step.
The 2nd step is to filter out only relevant results. When there are no relevant results, Google shows this message box:
What is their algorithm to show this box?
Idea 1: "grep -i {exact_keywords}"
For example, if I search a keyword like "Alexander Pope", the 24h Google query might return results about the pope, written by a guy called Alexander. That's not super relevant. My naive idea is to grep (case insensitive) the exact keyword "Alexander Pope".
But that might leave out some good results.
Any other ideas?

Handling null value inside Map

I'm learning to use BLOC pattern for consume API from newsapi.org. I have result JSON and Model like this from https://newsapi.org/v2/everythingq=flutter&apiKey=7f8eef4261bc4c29b26c4d5e93e8b5d6:
Json
{
"status": "ok",
"totalResults": 533,
"articles": [
{
"source": {
"id": "cnn",
"name": "CNN"
},
"author": "Sandee LaMotte, CNN",
"title": "Burnout linked to potentially deadly irregular heartbeat, study says",
"description": "If you're feeling bone-deep mental and physical exhaustion, or what is otherwise known as burnout, new research suggests you could be at a higher risk for a potentially fatal heart flutter.",
"url": "https://www.cnn.com/2020/01/13/health/burnout-linked-to-atrial-fibrillation-wellness/index.html",
"urlToImage": "https://cdn.cnn.com/cnnnext/dam/assets/200113120102-02-burnout-stock-super-tease.jpg",
"publishedAt": "2020-01-14T00:15:07Z",
"content": "(CNN)If you're feeling bone-deep mental and physical exhaustion, or what is otherwise known as burnout, new research suggests you could be at a higher risk for a potentially fatal heart flutter.\r\nAtrial fibrillation, also called AFib or AF, is the most common… [+4971 chars]"
},
{
"source": {
"id": "the-verge",
"name": "The Verge"
},
"author": "Ashley Carman",
"title": "The sex toy banned from CES last year is unlike anything we’ve ever seen",
"description": "Lora DiCarlo’s Osé personal massager made it to CES this year, after being banned and having its award revoked in 2019. The device is certainly innovative, using suction and movement to stimulate the G-spot and clitoris instead of vibration.",
"url": "https://www.theverge.com/2020/1/6/21051259/lora-dicarlo-sex-tech-toy-massager-awards-ban-ose-ces-2020",
"urlToImage": "https://cdn.vox-cdn.com/thumbor/G5zPZiQZgwqS9FqLqzUE3eyyLyA=/0x146:2040x1214/fit-in/1200x630/cdn.vox-cdn.com/uploads/chorus_asset/file/19576504/loradicarlo1.jpg",
"publishedAt": "2020-01-06T14:25:23Z",
"content": "Its certainly innovative\r\nAshley Carman / The Verge\r\nLora DiCarlo likely didnt intend to change CES forever, but the sexual wellness company and its personal massager accomplished just that last year. After having an award revoked and being banned from the sh… [+3125 chars]"
},
{
"source": {
"id": null,
"name": "Codemagic.io"
},
"author": null,
"title": "Flutter vs. Other Mobile Development Frameworks: A UI and Performance Experiment",
"description": "In this experiment we created the same app five times, each time with a different framework. The frameworks I used were native Android, native iOS, Flutter, Xamarin Forms and React Native",
"url": "https://blog.codemagic.io/flutter-vs-ios-android-reactnative-xamarin/",
"urlToImage": "https://blog.codemagic.io/uploads/Codemagic-io_Blog_Flutter-Versus-Other-Mobile-Development-Frameworks_1.png",
"publishedAt": "2020-01-03T21:26:48Z",
"content": "Written by Bram De Coninck\r\nIve already read a lot of articles about how Flutter compares to other mobile development frameworks, but most of them were written from a theoretical point of view. Its already been well established that Flutter is a solid choice … [+24309 chars]"
},
{
"source": {
"id": null,
"name": "Insider.com"
},
"author": "dschild#businessinsider.com (Darcy Schild), Darcy Schild",
"title": "Kylie Jenner shared a sneak peek of her new makeup collection inspired by her daughter, Stormi",
"description": "Kylie Jenner/YouTube; Kylie Jenner/Instagram Kylie Jenner, the makeup mogul behind Kylie Cosmetics, is launching a collection of new eyeshadows, Lip Kits, lip glosses, and a blush inspired by her 1-year-old daughter, Stormi. Jenner gave her followers a sneak …",
"url": "https://www.insider.com/kylie-jenner-cosmetics-stormi-collection-when-to-buy-2020-1",
"urlToImage": "https://i.insider.com/5e24bb4b3ac0c9452948fd10?width=1200&format=jpeg",
"publishedAt": "2020-01-19T20:24:58Z",
"content": "Kylie Jenner is launching a makeup collection inspired by her 1-year-old daughter, Stormi Webster.\r\nThe Stormi Collection by Kylie Cosmetics will be available for purchase starting February 1, Jenner said in an Instagram Story post on Saturday.\r\nIn November 2… [+2710 chars]"
},
]
}
NewsModel
class NewsModel {
final Map<String, dynamic> source;
final String author;
final String title;
final String description;
final String url;
final String urlToImage;
final String publishedAt;
final String content;
NewsModel({
this.source,
this.author,
this.title,
this.description,
this.url,
this.urlToImage,
this.publishedAt,
this.content,
});
NewsModel.fromJson(Map<String, dynamic> parsedJson)
: source = parsedJson['source']== null
? "Unknown Source"
: parsedJson['source'],
author = parsedJson['author'] == null
? "Unknown Author"
: parsedJson['author'],
title =
parsedJson['title'] == null ? "Unknown Title" : parsedJson['title'],
description = parsedJson['description'] == null
? "Unknown Description"
: parsedJson['description'],
url = parsedJson['url'] == null ? "Unknown Url" : parsedJson['url'],
urlToImage = parsedJson['urlToImage'] == null
? "https://homepages.cae.wisc.edu/~ece533/images/peppers.png"
: parsedJson['urlToImage'],
publishedAt = parsedJson['publishedAt'] == null
? "Unknown PublishedAt"
: parsedJson['publishedAt'],
content = parsedJson['content'] == null
? "Unknown Content"
: parsedJson['content'];
Map<String, dynamic> toMapForDb() {
return <String, dynamic>{
"source": source,
"author": author,
"title": title,
"description": description,
"url": url,
"urlToImage": urlToImage,
"publishedAt": publishedAt,
"content": content,
};
}
}
final newsModel = NewsModel();
source in this json is MAP,But one of its value is null (id). How to handling null value in my model ?
I'm trying handling this null value like this
source = parsedJson['source']['id'] == null? "Unknown Source" : parsedJson['source'],
But i get the error message Error From Bloc =type 'String' is not a subtype of type Map<String, dynamic>
My temporary solution to handling null value return Text(news.source["id"] ?? "null"); . But i want handling inside my model.
If you need BLOC source code
BLOC
import 'package:network/models/news_model.dart';
import 'package:repositories/repositories/news_repositories.dart';
import 'package:rxdart/subjects.dart';
class NewsBloc {
final _newsRepositories = NewsRepositories();
final _newsFetch = PublishSubject<List<NewsModel>>();
Stream<List<NewsModel>> get allEverythingNews => _newsFetch.stream;
Future<void> getEverythingNews() async {
try {
List<NewsModel> news = await _newsRepositories.getNewsEverything();
final newsAddSink = _newsFetch.sink.add(news);
return newsAddSink;
} catch (e) {
print("Error From Bloc =" + e.toString());
_newsFetch.sink.addError(e);
}
}
void dispose() {
_newsFetch.close();
}
}
final newsBloc = NewsBloc();
As can be seen from json you are getting object as a source and in your model you create a map to store source but when source is null then you are trying to assign String value to it. That’s why you are getting error.
Try To assign map like:
source = parsedJson['source']== null
? {"id": 0, "name": "Unknown Source"}
: parsedJson['source'],
By this error:
Error From Bloc =type 'String' is not a subtype of type Map
It is seems that the value provided in the NewsModel.fromJson() is a string and not a Map.
You need to do this:
NewsModel.fromJson(json.decode(STRING_FROM_API_RESPONSE))
Note that json is from import 'dart:convert';

BigCommerce Stencil - Retrieve Product Custom Fields in Product Card

I'm trying to retrieve each product's custom_fields data on the category list pages in BigCommerce Stencil. This documentation here, and the JSON product representation below, would suggest this is not possible.
It is hard for me to believe this functionality would be left out of Stencil, considering it was available in Blueprint.
{
"id": 691,
"name": "Archipelago Botanicals - Pomegranate Lip Gloss",
"url": "http://******.mybigcommerce.com/archipelago-botanicals-pomegranate-lip-gloss/",
"brand": {
"name": "Archipelago Botanicals"
},
"rating": 0,
"availability": "",
"summary": "Pomegranate lip gloss leaves lips hydrated, shiny and smooth. Apply liberally.Net Weight: 0.42 oz. / 12 g Mineral Oil, Polybutene, Octyidodecanol, Butylene, Ethylene, Styrene Copolymer, Ethylene, Propylene, Styrene Copolymer, C18-36 Acid Triglycerides, Fr",
"image": {
"data": "https://cdn3.bigcommerce.com/*****/images/stencil/{:size}/products/691/41439/arbopolipgl__77026.1464267682.jpg?c=2",
"alt": "Archipelago Botanicals - Pomegranate Lip Gloss"
},
"date_added": "Apr 7th 2016",
"qty_in_cart": 0,
"pre_order": false,
"has_options": false,
"show_cart_action": false,
"price": {
"without_tax": {
"formatted": "$5.00",
"value": 5
},
"rrp_without_tax": {
"formatted": "$12.50",
"value": 12.5
},
"saved": {
"formatted": "$7.50",
"value": 7.5
},
"tax_label": "Tax"
}
},
Am I missing something, or is this functionality not available on Stencil at this time?
Has anyone come up with a creative solution to retrieve this data inside each product card?
Thanks
The product card now allows this to be exposed. It provides an array of all custom fields associated with a product. Information on the product card object is here.
It was a change that had to be made in the BC core app and the fix was released on Sept 20th

YouTube Search API gives me less videos than requested per page, but also gives me a nextPageToken

The query below (First Request) says there are 24 results, but only returns me 3 items (when I asked for 20 per page)... fine... but why is it also giving me a nextPageToken. I thought, well, maybe if I get less than the 20 I'm asking for, I'm at the end...
But... in another case below (Second and Third Requests) it said there were 1717 videos and it gave me the first 20, but when I got the next page it only gave me 5... also with a nextPageToken.
Note: this does include a location and radius parameter... maybe this is not quite baked yet.
The question, then, is how can I tell when I have reached the end of my results?
(Edit: I found the reason for getting only 5 was that you still DO need to include maxResults along with nextPageToken, so maybe the answer is simply you're at the end if the nextPageToken is null or the number of items is less than resultsPerPage.)
First Request
https://www.googleapis.com/youtube/v3/search?maxResults=20&type=video&order=rating&q=Stanford%20University&location=37.86854355%2C-122.502038433&locationRadius=6000m&key=AIzaSyDIOVCAngpI-xPkb30W5c6ee0PSBV9KbF8&part=id%2Csnippet
{
"nextPageToken": "CBQQAA",
"pageInfo": {
"totalResults": 24,
"resultsPerPage": 20
},
"items": [
{
"id": {
"kind": "youtube#video",
"videoId": "WMfwyjJz9hs"
},
},
{
"id": {
"kind": "youtube#video",
"videoId": "aGnYxoGHYHQ"
},
},
{
"id": {
"kind": "youtube#video",
"videoId": "s50ZSCKA1zY"
},
}
]
}
Second and Third Requests
https://www.googleapis.com/youtube/v3/search?maxResults=20&type=video&order=rating&q=Sausalito&location=37.8590937%2C-122.4852507&locationRadius=6000m&key=AIzaSyDIOVCAngpI-xPkb30W5c6ee0PSBV9KbF8&part=id%2Csnippet
https://www.googleapis.com/youtube/v3/search?pageToken=CBQQAA&key=AIzaSyDIOVCAngpI-xPkb30W5c6ee0PSBV9KbF8&part=id%2Csnippet
I have similar trouble. I fixed bug by deleting field &order=rating in request. I think this parameter exclude videos with Zero(0) rating / this url return more results https://www.googleapis.com/youtube/v3/search?maxResults=20&type=video&order=rating&q=Sausalito&location=37.8590937%2C-122.4852507&locationRadius=6000m&key=AIzaSyDIOVCAngpI-xPkb30W5c6ee0PSBV9KbF8&part=id%2Csnippet
Default order parameter value is 'relevance' returns similar result or you can try &order=viewCount parameter return similar result to

Retrieve cover artwork using Spotify API

There is currently no way to retrieve the cover artwork using Spotify's Web API. Are there plans to implement these or any workarounds?
June 17th 2014:
Today Spotify released a new Web API.
It is now easy to retrieve cover artwork, as all endpoints includes an array of images for every item.
Search example:
curl -X GET "https://api.spotify.com/v1/search?q=tania%20bowra&type=artist"
{
"artists" : {
...
"items" : [ {
...
"images" : [ {
"height" : 640,
"url" : "https://d3rt1990lpmkn.cloudfront.net/original/f2798ddab0c7b76dc2d270b65c4f67ddef7f6718",
"width" : 640
}, {
"height" : 300,
"url" : "https://d3rt1990lpmkn.cloudfront.net/original/b414091165ea0f4172089c2fc67bb35aa37cfc55",
"width" : 300
}, {
"height" : 64,
"url" : "https://d3rt1990lpmkn.cloudfront.net/original/8522fc78be4bf4e83fea8e67bb742e7d3dfe21b4",
"width" : 64
...
} ],
...
}
}
Old Answer:
You can get the URL to the cover art by calling Spotify's oEmbed service:
https://embed.spotify.com/oembed/?url=spotify:track:6bc5scNUVa3h76T9nvpGIH
https://embed.spotify.com/oembed/?url=spotify:album:5NCz8TTIiax2h1XTnImAQ2
https://embed.spotify.com/oembed/?url=spotify:artist:7ae4vgLLhir2MCjyhgbGOQ
With JSONP:
https://embed.spotify.com/oembed/?url=spotify:artist:7ae4vgLLhir2MCjyhgbGOQ&callback=callme
http://open.spotify.com/ urls work as well:
https://embed.spotify.com/oembed/?url=http://open.spotify.com/track/6bc5scNUVa3h76T9nvpGIH
{
"provider_url": "https:\/\/www.spotify.com",
"version": "1.0",
"thumbnail_width": 300,
"height": 380,
"thumbnail_height": 300,
"title": "Gusgus - Within You",
"width": 300,
"thumbnail_url": "https:\/\/d3rt1990lpmkn.cloudfront.net\/cover\/f15552e72e1fcf02484d94553a7e7cd98049361a",
"provider_name": "Spotify",
"type": "rich",
"html": "<iframe src=\"https:\/\/embed.spotify.com\/?uri=spotify:track:6bc5scNUVa3h76T9nvpGIH\" width=\"300\" height=\"380\" frameborder=\"0\" allowtransparency=\"true\"><\/iframe>"
}
Notice the thumbnail_url:
https://d3rt1990lpmkn.cloudfront.net/cover/f15552e72e1fcf02484d94553a7e7cd98049361a
/cover/ represents the size of the thumbnail.
Available sizes: 60, 85, 120, 140, 160, 165, 230, 300, 320, and 640.
eg: https://d3rt1990lpmkn.cloudfront.net/640/f15552e72e1fcf02484d94553a7e7cd98049361a
There are plans to implement it, as in, we want it to be there, but nobody is working on it. It is mostly a legal problem with terms of use.
Technically, it is of course possible to figure it and access the same images that for instance open.spotify.com uses by parsing html. That is not allowed of course, but there is nothing technically that stops access.
(I work at Spotify)
The iTunes and Deezer API are also useful :
http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
http://developers.deezer.com/api/search