# Help translating curl command to HTTP.jl

**URL:** <https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790>\
**Category:** New to Julia\
**Tags:** question, package\
**Created:** [January 22, 2021, 5:08pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790 "2021-01-22T17:08:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 5:08pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/1 "2021-01-22T17:08:40Z")

</div>

I would like to scrape data using the Spotify API and I cannot seem to get the example curl command to translate to HTTP.jl

I am trying to get the accesstoken using my credentials. The relevant (working) curl command run through Julia is:

```julia
run(`curl -X "POST" -H "Authorization: Basic $refreshtoken" -d grant_type=client_credentials https://accounts.spotify.com/api/token -o creds.json`)

```

My attempt in HTTP.jl is:

```julia

HTTP.request("POST", 
    "https://accounts.spotify.com/api/token", 
    ["Authorization" => "Basic: $refreshtoken"],
    "grant_type=client_credentials")
# OR
 HTTP.request("POST", 
           "https://accounts.spotify.com/api/token", 
           ["Authorization" => "Basic $refreshtoken"],
           "grant_type=client_credentials", status_exception=false)

```

However I get an error:

```julia
ERROR: HTTP.ExceptionRequest.StatusError(400, "POST", "/api/token", HTTP.Messages.Response:
"""
HTTP/1.1 400 Bad Request
date: Fri, 22 Jan 2021 17:06:19 GMT
content-type: text/html; charset=utf-8
Content-Length: 1015
...
"""

```

EDIT:  
The following also works in python

```julia
import requests
out = requests.post("https://accounts.spotify.com/api/token",
              {"grant_type":"client_credentials"},
              headers={"Authorization": f"Basic {refreshtoken}"})

```

Help is much appreciated!

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [January 22, 2021, 5:20pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/2 "2021-01-22T17:20:53Z")

</div>

Grasping at straws here, but your curl and python have no colon after Basic but the HTTP header value does.

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 5:22pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/3 "2021-01-22T17:22:08Z")

</div>

Thanks! Good guess but unfortunately same error after removing the colon. I’ll update the post

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [January 22, 2021, 5:39pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/4 "2021-01-22T17:39:48Z")

</div>

Shouldn’t the body of the request be a JSON object? What happens if you do:

```julia
 HTTP.request(
    "POST", 
    "https://accounts.spotify.com/api/token", 
    ["Authorization" => "Basic $refreshtoken"],
    "{'grant_type': 'client_credentials'}",
    status_exception=false
)

```

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 5:47pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/5 "2021-01-22T17:47:36Z")

</div>

> [@mthelm85](#):
>
> ```julia-auto
> HTTP.request(
> "POST", 
> "https://accounts.spotify.com/api/token", 
> ["Authorization" => "Basic $refreshtoken"],
> "{'grant_type': 'client_credentials'}",
> status_exception=false
> )
> 
> ```

Unfortunately I get the same error.

This is the example in the spotify docs:

```julia-auto
curl -X "POST" -H "Authorization: Basic ZjM4ZjAw...WY0MzE=" -d grant_type=client_credentials https://accounts.spotify.com/api/token

```

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [January 22, 2021, 5:56pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/6 "2021-01-22T17:56:14Z")

</div>

What about:

```julia
 HTTP.request(
    "POST", 
    "https://accounts.spotify.com/api/token", 
    [
        "Authorization" => "Basic $refreshtoken",
        "Content_Type" => "application/x-www-form-urlencoded"
    ],
    "{'grant_type': 'client_credentials'}",
    status_exception=false
)

```

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 5:58pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/7 "2021-01-22T17:58:35Z")

</div>

> [@mthelm85](#):
>
> ```julia-auto
> HTTP.request(
> "POST", 
> "https://accounts.spotify.com/api/token", 
> [
> "Authorization" => "Basic $refreshtoken",
> "Content_Type" => "application/x-www-form-urlencoded"
> ],
> "{'grant_type': 'client_credentials'}",
> status_exception=false
> )
> 
> ```

Thank you for you effort!  
Still the same error.

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 6:04pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/8 "2021-01-22T18:04:46Z")

</div>

Once I have the token I can make request with HTTP.jl

e.g.

```julia
py"""
import requests
refreshtoken=$refreshtoken
out = requests.post("https://accounts.spotify.com/api/token",{"grant_type":"client_credentials"},headers={"Authorization": f"Basic {refreshtoken}"})
out = out.json()
"""
tkn = get(PyObject(py"out"), "access_token")
resp = HTTP.get("https://api.spotify.com/v1/playlists/1Sbiel38MM24OQi5Sc8cL2", 
    ["Content-Type"=>"application/json", 
    "Accept"=>"application/json", 
    "Authorization"=>"Bearer $tkn"]
    )

```

```julia
julia> JSON3.read(resp.body)
JSON3.Object{Array{UInt8,1},Array{UInt64,1}} with 15 entries:
  :collaborative => false
  :description => "Una Playlist con los éxitos actuales del Pop en español!! <a href=\"https://open.spotify.com/artist/0vR2qb8m9WHeZ5ByCbimq2\">Reik</…
  :external_urls => {…
  :followers => {…
  :href => "https://api.spotify.com/v1/playlists/1Sbiel38MM24OQi5Sc8cL2"
  :id => "1Sbiel38MM24OQi5Sc8cL2"
  :images => JSON3.Object[{…
  :name => "Mundo Pop En Español"
  ⋮ => ⋮

```

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [January 22, 2021, 6:25pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/9 "2021-01-22T18:25:31Z")

</div>

I signed up for an API key and when I do this:

```julia
HTTP.request(
    "POST", 
    "https://accounts.spotify.com/api/token", 
    [
        "Authorization" => "Basic $my_client_id:$my_client_secret",
        "Content-Type" => "application/x-www-form-urlencoded",
    ],
    "grant_type=client_credentials"
)

```

I get an “invalid client” error, which is different from the bad request error you’re getting. The Spotify docs say:

> Authorization _Required._  
> Base 64 encoded string that contains the client ID and client secret key. The field must have the format: Authorization: `Basic <base64 encoded client_id:client_secret>`

Are you following the `client_id:client_secret` format?

---

<div class="post-metadata">

**Author:** ![rikh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rikh/32/204104_2.png) [@rikh](https://discourse.julialang.org/u/rikh)\
**Post date:** [January 22, 2021, 7:21pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/10 "2021-01-22T19:21:16Z")

</div>

Small sidenote. You can also authenticate by placing the credentials in the url like

```julia
"https://$usename:$password@accounts.spotify.com/api/token"

```

to save some logic on your side ([source](https://github.com/JuliaWeb/HTTP.jl/blob/master/src/BasicAuthRequest.jl)). Also, basic authorization always requires an [username **and** password](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication), as mentioned by @mthelm85.

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 9:41pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/11 "2021-01-22T21:41:49Z")

</div>

> [@mthelm85](#):
>
> Are you following the `client_id:client_secret` format?

I bas64 encode the client\_id and client\_secret:

```julia-auto
refreshtoken = clientid * ':' * clientsecret
refreshtoken = base64encode(refreshtoken)

```

I can directly interpolate this into the `run(curl ...)` and python versions and it works

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 9:51pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/12 "2021-01-22T21:51:02Z")

</div>

Sorry I know very little about authentication etc. I am trying the following but still getting a 400 error:

```julia
HTTP.request(
           "POST", 
           "https://$user:$pw@accounts.spotify.com/api/token",
           [],"grant_type=client_credentials",
           status_exception=false
       )

```

where `user` and `pw` are my spotify user name an password, respectively. Am I misunderstanding this?

EDIT: Also tried with clientid and clientsecret without any luck.

---

<div class="post-metadata">

**Author:** ![rikh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rikh/32/204104_2.png) [@rikh](https://discourse.julialang.org/u/rikh)\
**Post date:** [January 22, 2021, 10:11pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/13 "2021-01-22T22:11:10Z")

</div>

No need to apologise 🙂

I meant user and password as an example. Clientid and clientsecret sounds like it should work. I guess, but can’t test since I’m not at a pc, that now the grant\_type is passed in the HTTP body instead of a header.

By the way, I understand your struggles completely. HTTP.jl is also usually a struggle for me about what should be where exactly

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 10:17pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/14 "2021-01-22T22:17:12Z")

</div>

I’ve gotten it to work with another API ([Chartmetric API Documentation](https://api.chartmetric.com/apidoc/)) earlier so I was kind of surprised it didn’t work now. It seems quite similar. In case someone is interested in music data this is the library for the Chartmetric API ([GitHub - danielw2904/ChartmetricScraper.jl](https://github.com/danielw2904/ChartmetricScraper.jl)). In the `token.jl` file I am doing a very similar request.

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [January 22, 2021, 10:21pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/15 "2021-01-22T22:21:20Z")

</div>

When I do:

```julia
curl -v -X "POST" -H "Authorization: Basic $refreshtoken" -d grant_type=client_credentials https://accounts.spotify.com/api/token

```

What is shown being requested is:

```julia
> Host: accounts.spotify.com
> user-agent: curl/7.74.0
> accept: */*
> authorization: Basic refreshtoken
> content-length: 29
> content-type: application/x-www-form-urlencoded

```

A few posts ago you tried adding `content-type` but you for had converted the data to json, try adding `content-type` to the headers. You might also try adding “user-agent” and “accept” to the headers as well. So:

```julia
HTTP.request("POST", 
    "https://accounts.spotify.com/api/token", 
    [
        "authorization" => "Basic: $refreshtoken",
        "user-agent" => "curl/7.74.0",
        "accept" => "*/*",
        "content-type" => "application/x-www-form-urlencoded"
    ],
    "grant_type=client_credentials")

```

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [January 22, 2021, 10:24pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/16 "2021-01-22T22:24:42Z")

</div>

You could also try changing the body to:

```julia
Vector{UInt8}("grant_type=client_credentials")

```

I’m not 100% sure if the passing a string vs passing a Vector results in the same data being sent to the server.

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 22, 2021, 10:49pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/17 "2021-01-22T22:49:46Z")

</div>

Thnak you for your suggestions!  
With this the response is

```julia
{"error":"invalid_client"}

```

---

<div class="post-metadata">

**Author:** ![tkluck](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkluck/32/15769_2.png) [@tkluck](https://discourse.julialang.org/u/tkluck)\
**Post date:** [January 24, 2021, 3:17pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/18 "2021-01-24T15:17:43Z")

</div>

Here’s a debugging suggestion: in a second terminal, run

```julia
nc -l 8080

```

and then replace `https://accounts.spotify.com` with `http://localhost:8080`. You can then compare exactly what’s the difference between the two requests. After that you don’t have to come up with guesses but you can just consult the HTTP.jl documentation to get what you need.

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 25, 2021, 12:51pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/19 "2021-01-25T12:51:36Z")

</div>

Thank you that solved it. I feel like I tried this before based on previous comments but anyways this is the command that works:

```julia
HTTP.post("https://accounts.spotify.com/api/token", 
    [
    "Authorization" => "Basic $refreshtoken", 
    "Accept" => "*/*", 
    "Content-Type" => "application/x-www-form-urlencoded"
    ],"grant_type=client_credentials")

```

---

<div class="post-metadata">

**Author:** ![danielw2904](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielw2904/32/10890_2.png) [@danielw2904](https://discourse.julialang.org/u/danielw2904)\
**Post date:** [January 25, 2021, 12:56pm UTC](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790/20 "2021-01-25T12:56:20Z")

</div>

Oh man that is my fault. Your suggestion works except

```julia
        "authorization" => "Basic: $refreshtoken",

```

should be

```julia
        "authorization" => "Basic $refreshtoken",

```

without the colon. I messed that up in the post  
Thanks again for your help!

[Next page](https://discourse.julialang.org/t/help-translating-curl-command-to-http-jl/53790.md?page=2)
