Search code examples
iosswiftinstagram-apihttp-status-code-403instagram-graph-api

iOS ask for Instagram Basic Api Fail, response status code: 403


I have checked the request body's data. These data run in Android or Postman are all successful, and will use new code to ask access_token every time. But the response status code is always 403 make me confused. However I just first time develop iOS project. I think maybe is somewhere error in my iOS code. here is the code request instagram basic display access_token API

func getShortAccessTokenInfo(requestBody: ShortAccessTokenRequestBody,completionHandler: @escaping (ShortAccessTokenResponse) -> Void) {
    
    let url = URL(string: "https://api.instagram.com/oauth/access_token")!
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let encoder = JSONEncoder()
    encoder.keyEncodingStrategy = .convertToSnakeCase
    guard let httpBody = try? encoder.encode(requestBody) else {
        print("Invalid httpBody")
        return
    }
    
    request.httpBody = httpBody
    print("httpBody \(httpBody) ")
    
    URLSession.shared.dataTask(with: request) {
        data, response, error in
        if let data = data {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            do {
                let response = try decoder.decode(ShortAccessTokenResponse.self, from: data)
                completionHandler(response)
            } catch {
                let httpResponse = response as! HTTPURLResponse
                print("\nhttpResponse.statusCode = \(httpResponse.statusCode)\n")
                print("\nhttpResponse.allHeaderFields = \(httpResponse.allHeaderFields)\n")
                print("\nhttpResponse.description = \(httpResponse.description)\n")

                
                let outputStr  = String(data: data, encoding: String.Encoding.utf8)! as String
                print("data = \(outputStr)")
            }
                        
        } else {
            print("No Data")
        }
    }.resume()
}

The Data Model is here

struct ShortAccessTokenRequestBody: Encodable {
    var clientId: String
    var clientSecret: String
    var code: String
    var grantType: String
    var redirectUri: String
}

struct ShortAccessTokenResponse: Decodable {
    var accessToken : String
    var userId : Int
}

here is log:

statusCode:

httpResponse.statusCode = 403

allHeaderFields:

httpResponse.allHeaderFields = [AnyHashable("origin-trial"): AuqWincgAuXeuu3KypEMnrrFEJHySaesyJS3EaIH40zvafzrU0Irhb7+5QwZpOqMZrPTjgvFl7Z5jJgy1dNAcQMAAAB6eyJvcmlnaW4iOiJodHRwczovL2luc3RhZ3JhbS5jb206NDQzIiwiZmVhdHVyZSI6IkNyb3NzT3JpZ2luT3BlbmVyUG9saWN5UmVwb3J0aW5nIiwiZXhwaXJ5IjoxNjEzNDExNjYyLCJpc1N1YmRvbWFpbiI6dHJ1ZX0=, AnyHashable("cross-origin-opener-policy"): same-origin-allow-popups;report-to="coop", AnyHashable("Cache-Control"): private, no-cache, no-store, must-revalidate, AnyHashable("report-to"): {"group": "coep", "max_age": 86400, "endpoints": [{"url": "/security/coep_report/"}]},{"group": "coop", "max_age": 86400, "endpoints": [{"url": "/security/coop_report/"}]}, AnyHashable("content-security-policy"): report-uri https://www.instagram.com/security/csp_report/; default-src 'self' https://www.instagram.com; img-src data: blob: https://.fbcdn.net https://.instagram.com https://.cdninstagram.com https://.facebook.com https://.fbsbx.com https://.giphy.com; font-src data: https://.fbcdn.net https://.instagram.com https://.cdninstagram.com; media-src 'self' blob: https://www.instagram.com https://.cdninstagram.com https://.fbcdn.net; manifest-src 'self' https://www.instagram.com; script-src 'self' https://instagram.com https://www.instagram.com https://.www.instagram.com https://.cdninstagram.com wss://www.instagram.com https://.facebook.com https://.fbcdn.net https://.facebook.net 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' https://.www.instagram.com https://www.instagram.com 'unsafe-inline'; connect-src 'self' https://instagram.com https://www.instagram.com https://.www.instagram.com https://graph.instagram.com https://.graph.instagram.com https://graphql.instagram.com https://.cdninstagram.com https://api.instagram.com https://i.instagram.com https://.i.instagram.com wss://www.instagram.com wss://edge-chat.instagram.com https://.facebook.com https://.fbcdn.net https://.facebook.net chrome-extension://boadgeojelhgndaghljhdicfkmllpafd blob:; worker-src 'self' blob: https://www.instagram.com; frame-src 'self' https://instagram.com https://www.instagram.com https://*.instagram.com https://staticxx.facebook.com https://www.facebook.com https://web.facebook.com https://connect.facebook.net https://m.facebook.com; object-src 'none'; upgrade-insecure-requests, AnyHashable("Content-Length"): 20676, AnyHashable("x-frame-options"): SAMEORIGIN, AnyHashable("Pragma"): no-cache, AnyHashable("cross-origin-embedder-policy-report-only"): require-corp;report-to="coep", AnyHashable("Strict-Transport-Security"): max-age=31536000, AnyHashable("x-content-type-options"): nosniff, AnyHashable("Content-Language"): zh-tw, AnyHashable("x-xss-protection"): 0, AnyHashable("proxy-status"): http_request_error; e_clientaddr="AcKYiNAO8yhMSZJyyEYudvZGWQzL-XB3-zoUHCoHbF8NHNnIr-i2ovQf3F3cMLaZ6NllIZz2Qo5Bgx6eJHw"; e_fb_binaryversion="AcLdEktTbz5wJ21gYaJEitTnDh51fwKoh1TWEJBnCTDeDsuWyGfrhaGoKLWBuytlTD_jNpYGEqTKkjuZHHl7upVezSs6uJlj8ok"; e_upip="AcJJDJlMUJsyHsIAGFauA9kxrXY2wohcrnfn50hqCMIY2ykTyJKp6Yzgq3HMhBdEfDpJdFdON7xvDmFgevxPXHhO4y4f7PITGNIpgvs"; e_proxy="AcJPFaA_DemVAz4l_ZIcLlO6dqLEWUrH1S3qyfM0Psu4Qqzm3d7g1IZeYuFfciVB_2EGkehYmN4GEjA"; e_fb_builduser="AcISyC6CAEhH54reK-ewAmKXLcNC8aeHIx4_8Dz6aY83oAk05yOr1kaVHEqYAN-Jcck"; e_fb_vipaddr="AcInfxChauRQiPpxzGfxHV2lNUNaz0TDhZFUIoS85agFhatn6NyYkeG6swkbzrGDNCmkyZk", http_request_error; e_clientaddr="AcIY794j6DB_pmP2rk4VsK1zivmZkN9gKrGfvjHfleRJNRB91E-eM7XwFHBZCUBY8zxtV5TVCl3bZAUl0ZOyUSNYP7HHQgvSuXGPRxosSOaG"; e_fb_binaryversion="AcITNqtpSK2R5tDP_gcliynnda3OUKCZgzK-Xsb-r4KXoTzmkEkQmC9Nir7f8yfGz50vSf-gAKhLabX9TQoI0dDOI6LlWW4BHaI"; e_upip="AcKdip7JMVCIyHNm4r3n_lc1FxZ8WRKNQWBDBUwsupTD4rNfKXV4LFfbOLVbapi7jcyqgp1OMZev9Mrb-zxwQ2fryGpF7P3D-Q"; e_proxy="AcI1jEPhkHHVfIX0U-99CwCpJd9bHFInKVHw9EqNNgHvgWSlCPPyPZ-hKEHGtNUxph6CrXt8H8drm0RL3DAn"; e_fb_builduser="AcKOj-xkkvFvzA7RHW34q4gu4tq7NuVcT_WRvsQwxdJFoGmDmQGrefnKdcJ7Hpb4KEo"; e_fb_vipaddr="AcKa3V32l88jLiYn7E5uzcjwzVyAsdvUFKuu1lo_qhJx5qKrGr1ffkqtyIr9Pxh8QrmPf1EHN5vZItcLz3j9_s-6lutm2G-44iYcaiE", AnyHashable("Content-Type"): text/html; charset=utf-8, AnyHashable("x-ig-push-state"): c2, AnyHashable("Set-Cookie"): rur="FTW\0541700458427\0541660136279:01f7f1716e996e603ddf484bdfbc12a6fad1ff6f56053129280eb54ca5906d3e6cf24459"; Domain=.instagram.com; HttpOnly; Path=/; Secure, AnyHashable("access-control-expose-headers"): X-IG-Set-WWW-Claim, AnyHashable("x-aed"): 46, AnyHashable("Vary"): Accept-Language, Cookie, AnyHashable("x-fb-trip-id"): 19638678, AnyHashable("Expires"): Sat, 01 Jan 2000 00:00:00 GMT, AnyHashable("Alt-Svc"): h3-29=":443"; ma=3600,h3-27=":443"; ma=3600, AnyHashable("x-ig-origin-region"): ftw, AnyHashable("Date"): Tue, 10 Aug 2021 12:57:59 GMT]

description:

<NSHTTPURLResponse: 0x280a5a6e0> { URL: https://api.instagram.com/oauth/access_token } { Status Code: 403, Headers {
"Alt-Svc" =     (
    "h3-29=\":443\"; ma=3600,h3-27=\":443\"; ma=3600"
);
"Cache-Control" =     (
    "private, no-cache, no-store, must-revalidate"
);
"Content-Language" =     (
    "zh-tw"
);
"Content-Length" =     (
    20676
);
"Content-Type" =     (
    "text/html; charset=utf-8"
);
Date =     (
    "Tue, 10 Aug 2021 12:57:59 GMT"
);
Expires =     (
    "Sat, 01 Jan 2000 00:00:00 GMT"
);
Pragma =     (
    "no-cache"
);
"Set-Cookie" =     (
    "rur=\"FTW\\0541700458427\\0541660136279:01f7f1716e996e603ddf484bdfbc12a6fad1ff6f56053129280eb54ca5906d3e6cf24459\"; Domain=.instagram.com; HttpOnly; Path=/; Secure"
);
"Strict-Transport-Security" =     (
    "max-age=31536000"
);
Vary =     (
    "Accept-Language, Cookie"
);
"access-control-expose-headers" =     (
    "X-IG-Set-WWW-Claim"
);
"content-security-policy" =     (
    "report-uri https://www.instagram.com/security/csp_report/; default-src 'self' https://www.instagram.com; img-src data: blob: https://*.fbcdn.net https://*.instagram.com https://*.cdninstagram.com https://*.facebook.com https://*.fbsbx.com https://*.giphy.com; font-src data: https://*.fbcdn.net https://*.instagram.com https://*.cdninstagram.com; media-src 'self' blob: https://www.instagram.com https://*.cdninstagram.com https://*.fbcdn.net; manifest-src 'self' https://www.instagram.com; script-src 'self' https://instagram.com https://www.instagram.com https://*.www.instagram.com https://*.cdninstagram.com wss://www.instagram.com https://*.facebook.com https://*.fbcdn.net https://*.facebook.net 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' https://*.www.instagram.com https://www.instagram.com 'unsafe-inline'; connect-src 'self' https://instagram.com https://www.instagram.com https://*.www.instagram.com https://graph.instagram.com https://*.graph.instagram.com https://graphql.instagram.com https://*.cdninstagram.com https://api.instagram.com https://i.instagram.com https://*.i.instagram.com wss://www.instagram.com wss://edge-chat.instagram.com https://*.facebook.com https://*.fbcdn.net https://*.facebook.net chrome-extension://boadgeojelhgndaghljhdicfkmllpafd blob:; worker-src 'self' blob: https://www.instagram.com; frame-src 'self' https://instagram.com https://www.instagram.com https://*.instagram.com https://staticxx.facebook.com https://www.facebook.com https://web.facebook.com https://connect.facebook.net https://m.facebook.com; object-src 'none'; upgrade-insecure-requests"
);
"cross-origin-embedder-policy-report-only" =     (
    "require-corp;report-to=\"coep\""
);
"cross-origin-opener-policy" =     (
    "same-origin-allow-popups;report-to=\"coop\""
);
"origin-trial" =     (
    "AuqWincgAuXeuu3KypEMnrrFEJHySaesyJS3EaIH40zvafzrU0Irhb7+5QwZpOqMZrPTjgvFl7Z5jJgy1dNAcQMAAAB6eyJvcmlnaW4iOiJodHRwczovL2luc3RhZ3JhbS5jb206NDQzIiwiZmVhdHVyZSI6IkNyb3NzT3JpZ2luT3BlbmVyUG9saWN5UmVwb3J0aW5nIiwiZXhwaXJ5IjoxNjEzNDExNjYyLCJpc1N1YmRvbWFpbiI6dHJ1ZX0="
);
"proxy-status" =     (
    "http_request_error; e_clientaddr=\"AcKYiNAO8yhMSZJyyEYudvZGWQzL-XB3-zoUHCoHbF8NHNnIr-i2ovQf3F3cMLaZ6NllIZz2Qo5Bgx6eJHw\"; e_fb_binaryversion=\"AcLdEktTbz5wJ21gYaJEitTnDh51fwKoh1TWEJBnCTDeDsuWyGfrhaGoKLWBuytlTD_jNpYGEqTKkjuZHHl7upVezSs6uJlj8ok\"; e_upip=\"AcJJDJlMUJsyHsIAGFauA9kxrXY2wohcrnfn50hqCMIY2ykTyJKp6Yzgq3HMhBdEfDpJdFdON7xvDmFgevxPXHhO4y4f7PITGNIpgvs\"; e_proxy=\"AcJPFaA_DemVAz4l_ZIcLlO6dqLEWUrH1S3qyfM0Psu4Qqzm3d7g1IZeYuFfciVB_2EGkehYmN4GEjA\"; e_fb_builduser=\"AcISyC6CAEhH54reK-ewAmKXLcNC8aeHIx4_8Dz6aY83oAk05yOr1kaVHEqYAN-Jcck\"; e_fb_vipaddr=\"AcInfxChauRQiPpxzGfxHV2lNUNaz0TDhZFUIoS85agFhatn6NyYkeG6swkbzrGDNCmkyZk\", http_request_error; e_clientaddr=\"AcIY794j6DB_pmP2rk4VsK1zivmZkN9gKrGfvjHfleRJNRB91E-eM7XwFHBZCUBY8zxtV5TVCl3bZAUl0ZOyUSNYP7HHQgvSuXGPRxosSOaG\"; e_fb_binaryversion=\"AcITNqtpSK2R5tDP_gcliynnda3OUKCZgzK-Xsb-r4KXoTzmkEkQmC9Nir7f8yfGz50vSf-gAKhLabX9TQoI0dDOI6LlWW4BHaI\"; e_upip=\"AcKdip7JMVCIyHNm4r3n_lc1FxZ8WRKNQWBDBUwsupTD4rNfKXV4LFfbOLVbapi7jcyqgp1OMZev9Mrb-zxwQ2fryGpF7P3D-Q\"; e_proxy=\"AcI1jEPhkHHVfIX0U-99CwCpJd9bHFInKVHw9EqNNgHvgWSlCPPyPZ-hKEHGtNUxph6CrXt8H8drm0RL3DAn\"; e_fb_builduser=\"AcKOj-xkkvFvzA7RHW34q4gu4tq7NuVcT_WRvsQwxdJFoGmDmQGrefnKdcJ7Hpb4KEo\"; e_fb_vipaddr=\"AcKa3V32l88jLiYn7E5uzcjwzVyAsdvUFKuu1lo_qhJx5qKrGr1ffkqtyIr9Pxh8QrmPf1EHN5vZItcLz3j9_s-6lutm2G-44iYcaiE\""
);
"report-to" =     (
    "{\"group\": \"coep\", \"max_age\": 86400, \"endpoints\": [{\"url\": \"/security/coep_report/\"}]},{\"group\": \"coop\", \"max_age\": 86400, \"endpoints\": [{\"url\": \"/security/coop_report/\"}]}"
);
"x-aed" =     (
    46
);
"x-content-type-options" =     (
    nosniff
);
"x-fb-trip-id" =     (
    19638678
);
"x-frame-options" =     (
    SAMEORIGIN
);
"x-ig-origin-region" =     (
    ftw
);
"x-ig-push-state" =     (
    c2
);
"x-xss-protection" =     (
    0
);

} }

data:

data = <!DOCTYPE html>
<html lang="zh-tw" class="no-js logged-in ">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">

        <title>
                  查無此頁 &bull; Instagram
                </title>

        
        <meta name="robots" content="noimageindex, noarchive">
        <meta name="apple-mobile-web-app-status-bar-style" content="default">
        <meta name="mobile-web-app-capable" content="yes">
        <meta name="theme-color" content="#ffffff">
        <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, viewport-fit=cover">
        <link rel="manifest" href="/data/manifest.json">

        
        
        

        <script type="text/javascript">
        (function() {
  var docElement = document.documentElement;
  var classRE = new RegExp('(^|\\s)no-js(\\s|$)');
  var className = docElement.className;
  docElement.className = className.replace(classRE, '$1js$2');
})();
</script>
        <script type="text/javascript">
(function() {
  if ('PerformanceObserver' in window && 'PerformancePaintTiming' in window) {
    window.__bufferedPerformance = [];
    var ob = new PerformanceObserver(function(e) {
      window.__bufferedPerformance.push.apply(window.__bufferedPerformance,e.getEntries());
    });
    ob.observe({entryTypes:['paint']});
  }

  window.__bufferedErrors = [];
  window.onerror = function(message, url, line, column, error) {
    window.__bufferedErrors.push({
      message: message,
      url: url,
      line: line,
      column: column,
      error: error
    });
    return false;
  };
  window.__initialData = {
    pending: true,
    waiting: []
  };
  function asyncFetchSharedData(extra) {
    var sharedDataReq = new XMLHttpRequest();
    sharedDataReq.onreadystatechange = function() {
          if (sharedDataReq.readyState === 4) {
            if(sharedDataReq.status === 200){
              var sharedData = JSON.parse(sharedDataReq.responseText);
              window.__initialDataLoaded(sharedData, extra);
            }
          }
        }
    sharedDataReq.open('GET', '/data/shared_data/', true);
    sharedDataReq.send(null);
  }
  function notifyLoaded(item, data) {
    item.pending = false;
    item.data = data;
    for (var i = 0;i < item.waiting.length; ++i) {
      item.waiting[i].resolve(item.data);
    }
    item.waiting = [];
  }
  function notifyError(item, msg) {
    item.pending = false;
    item.error = new Error(msg);
    for (var i = 0;i < item.waiting.length; ++i) {
      item.waiting[i].reject(item.error);
    }
    item.waiting = [];
  }
  window.__initialDataLoaded = function(initialData, extraData) {
    if (extraData) {
      for (var key in extraData) {
        initialData[key] = extraData[key];
      }
    }
    notifyLoaded(window.__initialData, initialData);
  };
  window.__initialDataError = function(msg) {
    notifyError(window.__initialData, msg);
  };
  window.__additionalData = {};
  window.__pendingAdditionalData = function(paths) {
    for (var i = 0;i < paths.length; ++i) {
      window.__additionalData[paths[i]] = {
        pending: true,
        waiting: []
      };
    }
  };
  window.__additionalDataLoaded = function(path, data) {
    if (path in window.__additionalData) {
      notifyLoaded(window.__additionalData[path], data);
    } else {
      console.error('Unexpected additional data loaded "' + path + '"');
    }
  };
  window.__additionalDataError = function(path, msg) {
    if (path in window.__additionalData) {
      notifyError(window.__additionalData[path], msg);
    } else {
      console.error('Unexpected additional data encountered an error "' + path + '": ' + msg);
    }
  };
  
})();
</script><script type="text/javascript">

Solution

  • Okay I've solved the same problem. Seems if you send a request with cookie to the Instagram's API, it will return 403 back. In iOS, URLRequest by default will add some cookies by the system, which causes this 403 problem.

    What you need to do is add:

    request.httpShouldHandleCookies = false
    

    to your request to disable adding cookies automatically by the system.