3

I am learning Python and I am trying to create a playlist using the Spotify web api but get a http 400 error: Error parsing json. I guess it has to do with an incorrect variable type in the token but I am having a really hard time debugging it as I can't figure out a way to see the post request in raw format.

Posting through the API requires authorizing and this is the script I've created for that:

import requests
import base64
requests.packages.urllib3.disable_warnings()

client_id = 'ID'
client_secret = 'SECRET'
redirect_uri = 'http://spotify.com/'
scope = 'playlist-modify-private playlist-read-private'

def request_token():

    #  1. Your application requests authorization
    auth_url = 'https://accounts.spotify.com/authorize'
    payload = {'client_id': client_id, 'response_type':'code','redirect_uri':redirect_uri}
    auth = requests.get(auth_url,params = payload)
    print '\nPlease go to this url to authorize ', auth.url

    #  2. The user is asked to authorize access within the scopes
    #  3. The user is redirected back to your specified URI
    resp_url = raw_input('\nThen please copy-paste the url you where redirected to: ')
    resp_code= resp_url.split("?code=")[1].split("&")[0]

    #  4. Your application requests refresh and access tokens
    token_url = 'https://accounts.spotify.com/api/token'
    payload = {'redirect_uri': redirect_uri,'code': resp_code, 'grant_type': 'authorization_code','scope':scope}
    auth_header = base64.b64encode(client_id + ':' + client_secret)
    headers = {'Authorization': 'Basic %s' % auth_header}
    req = requests.post(token_url, data=payload, headers=headers, verify=True)
    response = req.json()

    return response

This is the function actually trying to create the playlist using the authorization token (import authorizer is the function above):

import requests
import authorizer

def create_playlist(username, list_name):
    token = authorizer.request_token()
    access_token = token['access_token']
    auth_header = {'Authorization': 'Bearer {token}'.format(token=access_token), 'Content-Type': 'application/json'}
    api_url = 'https://api.spotify.com/v1/users/%s/playlists' % username
    payload = {'name': list_name, 'public': 'false'}
    r = requests.post(api_url, params=payload, headers=auth_header)

But whatever I try it only leads to a 400 error. Can anyone please point out my error here?

Erik
  • 71
  • 4
  • Could you provide more of the error output? Do you have the line number the error occurs on? – Celeo Apr 27 '15 at 20:11
  • How did you call `create_playlist`? – ljk321 Apr 28 '15 at 02:35
  • @Celeo, this is the response coming back from the Web API, so there's nothing in the code that's throwing an error. – Michael Thelin Apr 28 '15 at 07:31
  • My suspicion is that either last_name is empty, or that the public value 'false' needs to be an actual boolean and not a string. – Michael Thelin Apr 28 '15 at 07:32
  • @skyline75489 create_playlist('elissinger','testlist') – Erik Apr 29 '15 at 19:47
  • @MichaelThelin I use `create_playlist('elissinger','testlist')` to call the function, so both variables are populated. I tried changing 'public' to a boolean by giving it a capital 'F'. It was accepted but still the same HTTP error as a response to the post request: `"error": { "status": 400, "message": "Error parsing JSON." }` – Erik Apr 29 '15 at 19:52
  • Could you please try json.dumps(payload) instead of just payload? The payload might not be formatted correctly. (http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests) – Michael Thelin Apr 30 '15 at 07:56
  • @MichaelThelin Found the issue! It was a combination of changing to json.dumps(payload) like you suggested and changing the label from 'params' to 'data'. Weird, as in request_token() the json-formatting was done without json.dumps(payload) but there I didn't get any errors. – Erik May 01 '15 at 12:49
  • Great! :-D Put that in the answer and set it to the correct answer, so that others find it if they have the same issue :D – Michael Thelin May 07 '15 at 10:56
  • @MichaelThelin Many thanks! You spared me from going crazy and pulling any more of my hair from my head over the issue. Coded the rest so now it's all functioning both with creation and populating the playlist. – Erik May 07 '15 at 12:04

1 Answers1

4

Solved by adding a json.dumps for the input: json.dumps(payload) and changing the payload to be 'data' and not 'params' in the request.

So the new functioning request equals:

r = requests.post(api_url, data=json.dumps(payload), headers=auth_header)
Erik
  • 71
  • 4
  • 1
    Hmm it's interesting. I don't have a problem with `data=payload` in authorization (I don't need to call `json.dumps()`), but I have it in creating playlist. Fortunately your solution helped. Thanks. – akn Jun 24 '15 at 20:01