NA000022 NA000022 - 2 years ago 136
iOS Question

NSURLSession serialization error with post request

I am trying to get access token for Instagram but getting frequent error

You must provide client id
. I think it is a serialization problem as my parameters are not being serialized properly.
I tried it on
and it is working well but on
it throws error.


code = 400;
"error_message" = "You must provide a client_id";
"error_type" = OAuthException;

What am I doing wrong here while serializing it.

let instaInfoDict = NSDictionary(objects: ["client_id","client_secret","grant_type","redirect_uri","code"], forKeys: [kCLientIdInstagram,kCLientSecretIdInstagram,"authorization_code",kRedirectUriInstagram,code])
// Hit post request with params
WebServices().postRequest(kAccessTokenGenerationInstagram, bodyData: instaInfoDict, completionBlock: { (responseData) in



func postRequest(url:String, bodyData:NSDictionary, completionBlock:WSCompletionBlock){
if let url = NSURL(string: url){
let headers = [
"Accept": "application/json",
"content-type": "application/json"]

let session = NSURLSession.sharedSession()

let request = NSMutableURLRequest(URL: url, cachePolicy: .UseProtocolCachePolicy, timeoutInterval: 10)
request.HTTPMethod = "POST"
request.allHTTPHeaderFields = headers

request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(bodyData, options: [.PrettyPrinted])

let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) in
if error != nil {
// Handle error

//Parsing the data
let parsedData = parseJson(response as? NSData)

completionBlock!(responseData: parsedData)





I have tried this as well

request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(bodyData, options: NSJSONWritingOptions(rawValue: 0))

Answer Source

Seems that the problem is that the Content-Type should be application/x-www-form-urlencoded instead of application/json, also the way to send the parameters with this kind of Content-Type changes a little bit.

I made a small test and this code works for me:

static func generateAccessToken() {

    let params = ["client_id": "your_id",
                  "client_secret": "your_client_secret",
                  "grant_type": "authorization_code",
                  "redirect_uri": "",
                  "code": "the_code"]

    guard let url = NSURL(string: "") else {
    let request = NSMutableURLRequest(URL: url)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.HTTPMethod = "POST"

    let stringParams = params.paramsString()
    let dataParams = stringParams.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
    let paramsLength = String(format: "%d", dataParams!.length)
    request.setValue(paramsLength, forHTTPHeaderField: "Content-Length")
    request.HTTPBody = dataParams

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
        var json: AnyObject = [:]

        guard let data = data else {

        do {
            json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
        } catch {
            // Do nothing



to get the params in form of string I made this extension:

extension Dictionary {

func paramsString() -> String {
    var paramsString = [String]()
    for (key, value) in self {
        guard let stringValue = value as? String, let stringKey = key as? String else {
            return ""
        paramsString += [stringKey + "=" + "\(stringValue)"]

    return (paramsString.isEmpty ? "" : paramsString.joinWithSeparator("&"))


Hope it helps!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download