Using Environment Variables in cURL Command - Unix

For less quoting, read from standard input instead.

curl -k -X POST -H 'Content-Type: application/json' -d @- <<EOF
{ "username": "$USERNAME", "password": "$PASSWORD"}
EOF

-d @foo reads from a file named foo. If you use - as the file name, it reads from standard input. Here, standard input is supplied from a here document, which is treated as a double-quoted string without actually enclosing it in double quotes.


curl -k -X POST -H 'Content-Type: application/json' -d '{"username":"'$USERNAME'","password":"'$PASSWORD'"}'

Here the variable are placed outside of "'" quotes and will be expanded by shell (just like in echo $USERNAME). For example assuming that USRNAME=xxx and PASSWORD=yyy the argv[7] string passed to curl is {"username":"xxx","password":"yyy"}

And yes, this will not work when $USERNAME or $PASSWORD contain space characters.


Single quotes inhibit variable substitution, so use double quotes. The inner double quotes must then be escaped.

...  -d "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}"

Since this answer was written in 2015, it has become clear that this technique is insufficient to properly create JSON:

$ USERNAME=person1
$ PASSWORD="some \"gnarly 'password"
$ echo "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}"
{"username":"person1","password":"some "gnarly 'password"}
$ echo "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}" | jq .
parse error: Invalid numeric literal at line 1, column 47

The quoting problem are clear. The (shell) solutions are not

Current best practice: use a JSON-specific tool to create JSON:

  • jq

    $ jq -n -c --arg username "$USERNAME" --arg password "$PASSWORD" '$ARGS.named'
    {"username":"person1","password":"some \"gnarly 'password"}
    
  • jo

    $ jo "username=$USERNAME" "password=$PASSWORD"
    {"username":"person1","password":"some \"gnarly 'password"}
    

And with curl:

json=$( jq -n -c --arg username "$USERNAME" --arg password "$PASSWORD" '$ARGS.named' )
# or
json=$( jo "username=$USERNAME" "password=$PASSWORD" )

# then
curl ... -d "$json"