Get Facebook app_scoped_user_id From Facebook ID

Those of you who use the Facebook Graph API know that there were some big changes with the release of version 2.0. One of the biggest? Instead of returning a user's Facebook ID, the API is now returning an app_scoped_user_id, a unique identifier to each app/user combo.

If you were using the old Facebook ID, this change can cause big problems. Facebook says, "No matter what version they originally used to sign up for your app, the ID will remain the same for people who have already logged into your app. This change is backwards-compatible for anyone who has logged into your app at any point in the past." But, if you ever change the information you're requesting, Facebook will force users to re-authorize and you'll get the new app-scoped user ID, even for legacy users of your app.

Take me, for example. I never used to collect email addresses from Facebook on my running log; instead, I just used the Facebook ID to recognize the user. But, I also have other sites, such as my personal website that were using the Facebook sign in too, so now the API was returning two different IDs and I couldn't match up a future user across sites. Not good. To solve this, I decided to start collecting the email from Facebook, but doing so caused users to have to re-authenticate and suddenly I had two different Facebook IDs for each user and no way of tying them together. This led me to the big question…

How do you get a user's Facebook app_scoped_user_id from their Facebook ID?

Eventually, I came up with a solution, but it took a while. So, I'm hoping to save you that same hassle by posting the steps here.

Step 1: Create a business within Facebook. Even if you're not a business or are a business with only one site or app, start here. This documentation explains all the actions you'll need to take.

Step 2: Use the ids_for_business API endpoint to get data. The Facebook Graph API's ids_for_business endpoint will return a list of all app_scoped_user_id's for a user if you give it the user's original Facebook ID. Here's some example code:

1.   @session_start();
3.   $app_id = your_facebook_app_id;
4.   $app_secret = 'your_facebook_app_secret';
5.   $my_url = '';
6.   $debug = true;
8.   if (empty($_REQUEST['code'])) {
9.   	$_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
10.  	$dialog_url = ''.$app_id.'&redirect_uri='.urlencode($my_url).'&state='.$_SESSION['state'];
11.  	echo '<script>top.location.href=\''.$dialog_url.'\';</script>';
12.  	custom_die('Your browser isn\'t allowing you to be redirected to Facebook\'s log in page. Please lower your security settings to Medium High and then try again.');
13.  } elseif (!is_string($_REQUEST['code'])) {
14.  	custom_die('Code must be a string.'); //helps prevent malicious activity
15.  }
17.  //this link is helpful during testing because simply hitting refresh in your browser won't work (because <em>code</em> is already the query string)
18.  echo '<p><a href="'.$my_url.'">Try Again</a></p>';
20.  if ($_REQUEST['state'] == $_SESSION['state']) {
21.  	$token_url = ''.$app_id.'&redirect_uri='.urlencode($my_url).'&client_secret='.$app_secret.'&code='.strip_tags($_REQUEST['code']);
22.  	$response = file_get_contents($token_url);
23.  	$params = null;
24.  	parse_str($response, $params);
26.  	//$users is an example array of user data. replace as appropriate
27.  	foreach ($users as $user) {
28.  		$graph_url = ''.$user['facebook_id'].'&access_token='.$params['access_token'];
29.  		if ($debug) { echo '<p>Connecting to: '.$graph_url.'&hellip;</p>'; }
30.  		$data = json_decode(file_get_contents($graph_url));
31.  		if ($debug) { echo '<p>Response, stored in $data:</p><pre>'.print_r($data,true).'</pre>'; }
32.  		//here's where you should save your new app_scoped_user_id for each user
33.  	}
34.  } else {
35.  	custom_die('The state does not match. You may be a victim of CSRF.');
36.  }

Step 3: Save the app_scoped_user_id. After you get the new app-scoped ID, you can save it and then use it to recognize the user in the future.

That's all of the steps. Not too bad, right? I guess not. But… Now that I've done the work, allow me to rant a little about this new policy.

Why is Facebook not returning user IDs any more? Privacy is the claimed reason – they say this is to "better protect people's info" – but how is somebody's user ID personal info that needs to be protected? If anything, this is going to result in less privacy because it will cause sites (like mine) to start collecting email and using that as an identifier since the Facebook ID is no longer available.

Further, even if there is a valid reason for protecting the user's Facebook ID, this new change doesn't actually protect it. A call to the Graph API user endpoint returns a "link" field containing a URL that can be used to access the user's Facebook profile. A simple cURL request to that URL will return the ID to you, no problem. In fact, I took a look at the source of my own Facebook profile page (after accessing it from that URL) and found my Facebook ID listed 227 times. That's some protected info there, huh?


September 6, 2014, 7:30 am
I ran into a similar problem. Thank you for the code, that got me around it. As to why the API change, I have no idea…
December 12, 2014, 4:44 am
I use your suggestions. Everything worked fine up to December 10th but now I receive a weird error:
(#100) Invalid user ID. Can only query IDs of people who use your app.
Can anybody confirm me or not if someone has the same issue?
December 28, 2014, 9:39 pm
The link from the Graph API contains appScopedUserId, not the real ID. When you access that link it will redirect you to the profile page of that user. Eureka! That sounds like a victory. Unfortunately you get redirected only if you are currently signed-in. In other words, the "simple cURL request" of yours only gives you a page asking you (your request) to sign-in.

That means that there is currently no way of finding out Facebook ID for *new* users coming to your website. All you get is appScopedUserId.

Currently the only way I see is to sign-in to Fb using your browser, copy the headers+cookies, and use those with your cURL request. But I think it is clear that when you get caught your app will get banned.
Fuck Facebook.
November 11, 2015, 9:14 pm
One annoying thing about this is that a FB Test app of your current app will NOT return the 'real' FB user id and will instead return the app scoped id. It makes sense as to why since the test app has a separate app id.

Anyway…it means you must test against your live FB app id or do some tweaking on your data so you use the app scoped user id if you want to use a FB test app. In my case, I just added the domain to the App Domains list of the FB app.

Leave a Comment

Name and email are required. Your email will not be published.

This post was published on September 5th, 2014 by Robert James Reese in the following categories: Facebook and PHP. Before using any of the code or other content in this post, you must read and agree to our Terms & Conditions.