24

I have multiple query parameters that I want to send in an HTTP PUT operation using curl. How do I encode the query parameters? Example:

$ curl -X PUT http://example.com/resource/1?param1=value%201&param2=value2

If 'value 1' contains spaces or other characters that are interpreted by the shell, the command will not parse correctly.

2Aguy
  • 3,955
  • 5
  • 22
  • 28

3 Answers3

49

The solution is to use the -G switch in combination with the --data-urlencode switch. Using the original example, the command would look like the following:

$ curl -X PUT -G 'http://example.com/resource/1' --data-urlencode 'param1=value 1' --data-urlencode param2=value2

The -G switch causes the parameters encoded with the --data-urlencode switches to be appended to the end of the http URL with a ? separator.

In the example, the value of param1, would be encoded as value%201, where %20 is the encoded value for a space character.

2Aguy
  • 3,955
  • 5
  • 22
  • 28
  • @2Agyu what about url encoding GET query/parameters? Those that are part of url and not part of POST request? – Andrew May 23 '22 at 09:19
1

I was wanting to use URL-encoded query parameters and a body/payload (in my case, a JSON). It seems like the only way to get curl to do this is to supply a URL which includes the encoded query string - in other words, to URL-encode the query parameters yourself.

An excellent answer to that last part was provided by Sergey and Bruno here: https://stackoverflow.com/a/10797966/19632250

Putting these together into something usable, I got the following script.

#!/bin/bash
#

urlEncode() {
    echo $1 | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | sed -E 's/..(.*).../\1/'
}

echo '{"data":"this is some test data"}' > /tmp/test

url="https://example.com/test?$(urlEncode "param1")=$(urlEncode "value 1")&$(urlEncode "param2")=$(urlEncode "value 2")"

# Payload from a file:
curl -X POST $url -H 'Content-Type: application/json' -T "/tmp/test"

# Alternative:
#curl -X POST $url -H 'Content-Type: application/json' --data '{"data":"this is some test data"}'

-1

PUT requests are actually working like POST requests.

You should use $ curl -X PUT --data "param1=value1&param2=value2" http://whatever

Data should be x-www-form-urlencoded.

EDIT: Though it is totally contrary to the standard, I've seen instances where the request body must both had to be appended as a query string and passed as form-data.

LinkedIn API is the most notable.