{"id":13527260,"url":"https://github.com/node-facebook/facebook-node-sdk","last_synced_at":"2025-10-05T08:30:48.457Z","repository":{"id":57233597,"uuid":"42683620","full_name":"node-facebook/facebook-node-sdk","owner":"node-facebook","description":"Modeled from the (Facebook Javascript SDK), now with the facebook-node-sdk you can now easily write the same code and share between your server (nodejs) and the client (Facebook Javascript SDK).","archived":false,"fork":true,"pushed_at":"2023-01-10T02:19:14.000Z","size":1692,"stargazers_count":526,"open_issues_count":30,"forks_count":116,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-01-23T03:33:28.500Z","etag":null,"topics":["api","facebook","facebook-api","facebook-graph","facebook-graph-api","facebook-login","facebook-sdk","node-js","nodejs","sdk"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Thuzi/facebook-node-sdk","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/node-facebook.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-17T21:44:45.000Z","updated_at":"2025-01-15T19:50:50.000Z","dependencies_parsed_at":"2023-02-08T16:45:20.479Z","dependency_job_id":null,"html_url":"https://github.com/node-facebook/facebook-node-sdk","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-facebook%2Ffacebook-node-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-facebook%2Ffacebook-node-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-facebook%2Ffacebook-node-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-facebook%2Ffacebook-node-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/node-facebook","download_url":"https://codeload.github.com/node-facebook/facebook-node-sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235378537,"owners_count":18980464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","facebook","facebook-api","facebook-graph","facebook-graph-api","facebook-login","facebook-sdk","node-js","nodejs","sdk"],"created_at":"2024-08-01T06:01:44.324Z","updated_at":"2025-10-05T08:30:48.146Z","avatar_url":"https://github.com/node-facebook.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# NodeJS Library for Facebook [![Build Status](https://travis-ci.org/node-facebook/facebook-node-sdk.svg?branch=master)](https://travis-ci.org/node-facebook/facebook-node-sdk) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnode-facebook%2Ffacebook-node-sdk.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnode-facebook%2Ffacebook-node-sdk?ref=badge_shield)\n\nWith facebook-node-sdk you can now easily write the same code and share between your server (nodejs) and the client ([Facebook Javascript SDK](https://developers.facebook.com/docs/reference/javascript/)).\n\n**Author:** [Thuzi](http://www.thuzi.com)\n\n**Maintainer** [Daniel Friesen](https://github.com/dantman)\n\n**License:** Apache v2\n\n# Installing facebook-node-sdk\n\n```\nnpm install fb\n```\n\n```js\n// Using ES2015 import\nimport FB, {FacebookApiException} from 'fb';\n\n// Using require() in ES2015\nconst {FB, FacebookApiException} = require('fb');\n\n// Using require() in ES5\nvar FB = require('fb').default;\n```\n\n## Library usage\n\nLibraries can isolate themselves from the options belonging to the default `FB` by creating an instance of the `Facebook` class.\n\n```js\n// ES2015 modules\nimport {Facebook, FacebookApiException} from 'fb';\nconst fb = new Facebook(options);\n\n// ES2015 w/ require()\nconst {Facebook, FacebookApiException} = require('fb'),\nconst fb = new Facebook(options);\n\n// ES5\nvar Facebook = require('fb').Facebook,\n    fb = new Facebook(options);\n```\n\n## Multi-app usage\n\nApplications that run on behalf of multiple apps with different Facebook appIds and secrets can use `.extend` (on `FB` or any `Facebook` instance) to create a new instance which inherits options not set on it from the instance it is created from (like the API `version` your application is coded against).\n\n```js\nFB.options({version: 'v2.4'});\nvar fooApp = FB.extend({appId: 'foo_id', appSecret: 'secret'}),\n    barApp = FB.extend({appId: 'bar_id', appSecret: 'secret'});\n```\n\n## Graph Api\n\n### Get\n\n```js\nFB.api('4', function (res) {\n  if(!res || res.error) {\n   console.log(!res ? 'error occurred' : res.error);\n   return;\n  }\n  console.log(res.id);\n  console.log(res.name);\n});\n```\n\n__Passing Parameters__\n\n```js\nFB.api('4', { fields: 'id,name,picture.type(large)' }, function (res) {\n  if(!res || res.error) {\n    console.log(!res ? 'error occurred' : res.error);\n    return;\n  }\n  console.log(res.id);\n  console.log(res.name);\n});\n```\n\n### Post\n\n```js\nFB.setAccessToken('access_token');\n\nvar body = 'My first post using facebook-node-sdk';\nFB.api('me/feed', 'post', { message: body }, function (res) {\n  if(!res || res.error) {\n    console.log(!res ? 'error occurred' : res.error);\n    return;\n  }\n  console.log('Post Id: ' + res.id);\n});\n```\n\n#### Upload\n\n```js\nFB.setAccessToken('access_token');\n\nFB.api('me/photos', 'post', { source: fs.createReadStream('my-vacation.jpg'), caption: 'My vacation' }, function (res) {\n  if(!res || res.error) {\n    console.log(!res ? 'error occurred' : res.error);\n    return;\n  }\n  console.log('Post Id: ' + res.post_id);\n});\n\nFB.api('me/photos', 'post', { source: { value: photoBuffer, options: { filename: 'upload.jpg', contentType: 'image/jpeg' } }, caption: 'My vacation' }, function (res) {\n  if(!res || res.error) {\n    console.log(!res ? 'error occurred' : res.error);\n    return;\n  }\n  console.log('Post Id: ' + res.post_id);\n});\n```\n\n### Delete\n\n```js\nFB.setAccessToken('access_token');\n\nvar postId = '1234567890';\nFB.api(postId, 'delete', function (res) {\n  if(!res || res.error) {\n    console.log(!res ? 'error occurred' : res.error);\n    return;\n  }\n  console.log('Post was deleted');\n});\n```\n\n## Batch Requests\n\n```js\nFB.setAccessToken('access_token');\n\nvar extractEtag;\nFB.api('', 'post', {\n    batch: [\n        { method: 'get', relative_url: '4' },\n        { method: 'get', relative_url: 'me/friends?limit=50' },\n        { method: 'get', relative_url: '4', headers: { 'If-None-Match': '\"7de572574f2a822b65ecd9eb8acef8f476e983e1\"' } }, /* etags */\n        { method: 'get', relative_url: 'me/friends?limit=1', name: 'one-friend' /* , omit_response_on_success: false */ },\n        { method: 'get', relative_url: '{result=one-friend:$.data.0.id}/feed?limit=5'}\n    ]\n}, function(res) {\n    var res0, res1, res2, res3, res4,\n        etag1;\n\n    if(!res || res.error) {\n        console.log(!res ? 'error occurred' : res.error);\n        return;\n    }\n\n    res0 = JSON.parse(res[0].body);\n    res1 = JSON.parse(res[1].body);\n    res2 = res[2].code === 304 ? undefined : JSON.parse(res[2].body);   // special case for not-modified responses\n                                                                        // set res2 as undefined if response wasn't modified.\n    res3 = res[3] === null ? null : JSON.parse(res[3].body);\n    res4 = res3 === null ? JSON.parse(res[4].body) : undefined; // set result as undefined if previous dependency failed\n\n    if(res0.error) {\n        console.log(res0.error);\n    } else {\n        console.log('Hi ' + res0.name);\n        etag1 = extractETag(res[0]); // use this etag when making the second request.\n        console.log(etag1);\n    }\n\n    if(res1.error) {\n        console.log(res1.error);\n    } else {\n        console.log(res1);\n    }\n\n    // check if there are any new updates\n    if(typeof res2 !== \"undefined\") {\n        // make sure there was no error\n        if(res2.error) {\n            console.log(error);\n        } else {\n            console.log('new update available');\n            console.log(res2);\n        }\n    }\n    else {\n        console.log('no updates');\n    }\n\n    // check if dependency executed successfully\n    if(res[3] === null) {\n        // then check if the result it self doesn't have any errors.\n        if(res4.error) {\n            console.log(res4.error);\n        } else {\n            console.log(res4);\n        }\n    } else {\n        console.log(res3.error);\n    }\n});\n\nextractETag = function(res) {\n    var etag, header, headerIndex;\n    for(headerIndex in res.headers) {\n        header = res.headers[headerIndex];\n        if(header.name === 'ETag') {\n            etag = header.value;\n        }\n    }\n    return etag;\n};\n```\n\n### Post\n\n```js\nFB.setAccessToken('access_token');\n\nvar message = 'Hi from facebook-node-js';\nFB.api('', 'post', {\n    batch: [\n        { method: 'post', relative_url: 'me/feed', body:'message=' + encodeURIComponent(message) }\n    ]\n}, function (res) {\n    var res0;\n\n    if(!res || res.error) {\n        console.log(!res ? 'error occurred' : res.error);\n        return;\n    }\n\n    res0 = JSON.parse(res[0].body);\n\n    if(res0.error) {\n        console.log(res0.error);\n    } else {\n        console.log('Post Id: ' + res0.id);\n    }\n});\n```\n\n## OAuth Requests\n\n*This is a non-standard behavior and does not work in the official client side FB JS SDK.*\n\nfacebook-node-sdk is capable of handling oauth requests which return non-json responses. You can use it by calling `api` method.\n\n### Get facebook application access token\n\n```js\n\nFB.api('oauth/access_token', {\n    client_id: 'app_id',\n    client_secret: 'app_secret',\n    grant_type: 'client_credentials'\n}, function (res) {\n    if(!res || res.error) {\n        console.log(!res ? 'error occurred' : res.error);\n        return;\n    }\n\n    var accessToken = res.access_token;\n});\n```\n\n### Exchange code for access token\n\n```js\n\nFB.api('oauth/access_token', {\n    client_id: 'app_id',\n    client_secret: 'app_secret',\n    redirect_uri: 'http://yoururl.com/callback',\n    code: 'code'\n}, function (res) {\n    if(!res || res.error) {\n        console.log(!res ? 'error occurred' : res.error);\n        return;\n    }\n\n    var accessToken = res.access_token;\n    var expires = res.expires ? res.expires : 0;\n});\n```\n\nYou can safely extract the code from the url using the `url` module. Always make sure to handle invalid oauth callback as\nwell as error.\n\n```js\nvar url = require('url');\n\nvar urlToParse = 'http://yoururl.com/callback?code=.....#_=_';\nvar result = url.parse(urlToParse, true);\nif(result.query.error) {\n    if(result.query.error_description) {\n        console.log(result.query.error_description);\n    } else {\n        console.log(result.query.error);\n    }\n    return;\n} else if (!result.query.code) {\n    console.log('not a oauth callback');\n    return;\n}\n\nvar code = result.query.code;\n```\n\n### Extend expiry time of the access token\n\n```js\n\nFB.api('oauth/access_token', {\n    client_id: 'client_id',\n    client_secret: 'client_secret',\n    grant_type: 'fb_exchange_token',\n    fb_exchange_token: 'existing_access_token'\n}, function (res) {\n    if(!res || res.error) {\n        console.log(!res ? 'error occurred' : res.error);\n        return;\n    }\n\n    var accessToken = res.access_token;\n    var expires = res.expires ? res.expires : 0;\n});\n```\n\n## Access Tokens\n\n### setAccessToken\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\n**Warning**: Due to Node's asynchronous nature, you should not use `setAccessToken` when `FB` is used on behalf of for multiple users.\n\n```js\nFB.setAccessToken('access_token');\n```\n\nIf you want to use the api compatible with FB JS SDK, pass `access_token` as parameter.\n\n```js\nFB.api('me', { fields: 'id,name', access_token: 'access_token' }, function (res) {\n    console.log(res);\n});\n```\n\n### withAccessToken\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\nUsing `FB.extend` this returns a new FB object that inherits the same options but has an accessToken specific to it set.\n\n```js\nvar fb = FB.withAccessToken('access_token');\n```\n\n### getAccessToken\n*Unlike `setAccessToken` this is a standard api and exists in FB JS SDK.*\n\n```js\nFB.setAccessToken('access_token');\nvar accessToken = FB.getAccessToken();\n```\n\n### AppSecret Proof\nFor improved security, as soon as you provide an app secret and an access token, the\nlibrary automatically computes and adds the appsecret_proof parameter to your requests.\n\n## Rate limiting\nCurrent rate limit values are updated after each response received.\n\u003eIf your app is making enough calls to be considered for rate limiting by our system, we return an X-App-Usage HTTP header.\n\nThat means if your API usage is low enough, Facebook don't send any information about rate limits and we consider them as 0\n### getAppUsage\n```js\nvar appUsage = FB.getAppUsage();\n/*\n  {\n    callCount: 0,\n    totalTime: 0,\n    totalCPUTime: 0\n  }\n*/\n```\n\n### getPageUsage\n```js\nvar pageUsage = FB.getPageUsage();\n/*\n{\n    callCount: 0,\n    totalTime: 0,\n    totalCPUTime: 0\n}\n*/\n```\n\n## Configuration options\n\n### options\n\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\nWhen this method is called with no parameters it will return all of the current options.\n\n```js\nvar options = FB.options();\n```\n\nWhen this method is called with a string it will return the value of the option if exists, null if it does not.\n\n```js\nvar timeout = FB.options('timeout');\n```\n\nWhen this method is called with an object it will merge the object onto the previous options object.\n```js\nFB.options({accessToken: 'abc'}); //equivalent to calling setAccessToken('abc')\nFB.options({timeout: 1000, accessToken: 'XYZ'}); //will set timeout and accessToken options\nvar timeout = FB.options('timeout'); //will get a timeout of 1000\nvar accessToken = FB.options('accessToken'); //will get the accessToken of 'XYZ'\n```\n\nThe existing options are:\n* `'accessToken'` string representing the Facebook accessToken to be used for requests. This is the same option that is updated by the `setAccessToken` and `getAccessToken` methods.\n* `'appId'` The ID of your app, found in your app's dashboard.\n* `'appSecret'` string representing the Facebook application secret.\n* `'version'` [default=`'v2.3'`] string representing the Facebook api version to use. Defaults to the oldest available version of the api.\n* `'proxy'` string representing an HTTP proxy to be used. Support proxy Auth with Basic Auth, embedding the auth info in the uri: 'http://[username:password@]proxy[:port]' (parameters in brackets are optional).\n* `'agent'` a custom `https.Agent` to use for the request.\n* `'timeout'` integer number of milliseconds to wait for a response. Requests that have not received a response in *X* ms. If set to null or 0 no timeout will exist. On timeout an error object will be returned to the api callback with the error code of `'ETIMEDOUT'` (example below).\n* `'scope'` string representing the Facebook scope to use in `getLoginUrl`.\n* `'redirectUri'` string representing the Facebook redirect_uri to use in `getLoginUrl`.\n* `'Promise'` Promise implementation to use when `FB.api` is called without a callback. Defaults to the Promise implementation returned by `require('any-promise')`.\n\n### version\n\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\nGets the string representation of the facebook-node-sdk library version.\n\n```js\nvar version = FB.version;\n```\n\n## Parsing Signed Request\n\n### parseSignedRequest\n\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\n```js\nvar signedRequestValue = 'signed_request_value';\nvar appSecret = 'app_secret';\n\nvar signedRequest  = FB.parseSignedRequest(signedRequestValue, appSecret);\nif(signedRequest) {\n    var accessToken = signedRequest.oauth_token;\n    var userId = signedRequest.user_id;\n    var userCountry = signedRequest.user.country;\n}\n```\n\n*Note: parseSignedRequest will return undefined if validation fails. Always remember to check the result of parseSignedRequest before accessing the result.*\n\nIf you already set the appSecret in options, you can ignore the second parameter when calling parseSignedRequest. If you do pass the second parameter it will use the appSecret passed in parameter instead of using appSecret from options.\n\nIf appSecret is absent, parseSignedRequest will throw an error.\n\n```js\nFB.options({'appSecret': 'app_secret'});\n\nvar signedRequestValue = 'signed_request_value';\n\nvar signedRequest  = FB.parseSignedRequest(signedRequestValue);\nif(signedRequest) {\n    var accessToken = signedRequest.oauth_token;\n    var userId = signedRequest.user_id;\n    var userCountry = signedRequest.user.country;\n}\n```\n\n## Manual Login Flow\n\n### getLoginUrl\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\nThis returns the redirect url for a [manual login flow](https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow).\n\n```js\nFB.getLoginUrl({\n    scope: 'email,user_likes',\n    redirect_uri: 'http://example.com/'\n});\n```\n\nThese options are accepted and all correspond to url parameters documented in Facebook's manual login flow documentation.\n\n* `'appId'`/`'client_id'` [default=`FB.options('appId')`] The ID of your app, found in your app's dashboard.\n* `'redirectUri'`/`'redirect_uri'` [default=`FB.options('redirectUri')`] The URL that you want to redirect the person logging in back to. This URL will capture the response from the Login Dialog.\n* `'scope'` [default=`FB.options('scope')`] A comma separated list of Permissions to request from the person using your app.\n* `'display'` Can be set to 'popup'.\n* `'state'` An arbitrary unique string created by your app to guard against Cross-site Request Forgery.\n* `'responseType'`/`'response_type'` [default=`'code'`] Determines whether the response data included when the redirect back to the app occurs is in URL parameters or fragments.\n\n\n## Error handling\n\n*Note: Facebook is not consistent with their error format, and different systems can fail causing different error formats*\n\nSome examples of various error codes you can check for:\n* `'ECONNRESET'` - connection reset by peer\n* `'ETIMEDOUT'` - connection timed out\n* `'ESOCKETTIMEDOUT'` - socket timed out\n* `'JSONPARSE'` - could not parse JSON response, happens when the FB API has availability issues. It sometimes returns HTML\n\n```js\nFB.options({timeout: 1, accessToken: 'access_token'});\n\nFB.api('/me', function (res) {\n    if(res \u0026\u0026 res.error) {\n        if(res.error.code === 'ETIMEDOUT') {\n            console.log('request timeout');\n        }\n        else {\n            console.log('error', res.error);\n        }\n    }\n    else {\n        console.log(res);\n    }\n});\n```\n\n### Debugging\n\nIf you need to submit a bug report to Facebook you can run your application with `DEBUG=fb:req,fb:fbdebug` and request information will be output to your console along with `x-fb-trace-id`, `x-fb-rev`, and `x-fb-debug` headers you can include.\n\n## Promise based interface\n\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\nWhen `FB.api` is called without a callback it will instead return a Promise that will either resolve with the same response as `FB.api` or be rejected with a `FacebookApiException` error.\n\n```js\n// In an async function\nasync function example() {\n    try {\n        var response = await FB.api('4');\n        console.log(response);\n    }\n    catch(error) {\n        if(error.response.error.code === 'ETIMEDOUT') {\n            console.log('request timeout');\n        }\n        else {\n            console.log('error', error.message);\n        }\n    }\n}\n\n// Using plain promise callbacks\nFB.api('4')\n    .then((response) =\u003e {\n        console.log(response);\n    })\n    .catch((error) =\u003e {\n        if(error.response.error.code === 'ETIMEDOUT') {\n            console.log('request timeout');\n        }\n        else {\n            console.log('error', error.message);\n        }\n    });\n```\n\nThe promises returned are native Promises. However you can override the promise implementation used with a 3rd party library by setting the `Promise` option.\n\n```js\n// Promise option\nimport FB from 'fb';\n\nFB.options({\n    Promise: require('bluebird')\n});\nlet response = await FB.api('4');\n\n// Promise option in a library\nimport {Facebook} from 'fb';\nvar fb = new Facebook({\n    Promise: require('bluebird')\n});\nlet response = await fb.api('4');\n```\n\n## Node style callback with FB.napi\n\n*This is a non-standard api and does not exist in the official client side FB JS SDK.*\n\n`FB.napi` takes the same input as `FB.api`. Only the callback parameters is different. In the original `FB.api`, the callback expects one parameter which is the response. In `FB.napi` the callback expects two parameters instead of one and follows the node standards. The first parameter is an error which is always of type `FacebookApiException` and the second parameter is the same response as in `FB.api`. Error response can be accessed using `error.response` which is the same response as the response when using `FB.api`.\n\n```js\nFB.napi('4', function(error, response) {\n    if(error) {\n        if(error.response.error.code === 'ETIMEDOUT') {\n            console.log('request timeout');\n        }\n        else {\n            console.log('error', error.message);\n        }\n    } else {\n        console.log(response);\n    }\n});\n```\n\n`FB.napi` was added especially to make it easier to work with async control flow libraries.\n\nHere are some examples of using facebook-node-sdk with [Step](https://npmjs.org/package/step).\n\nYou will need to install `step`.\n\n```fb\nnpm install step\n```\n\n### FB.api with Step\n\n```js\nvar FB      = require('fb').default,\n    Step    = require('step');\n\nStep(\n    function getUser() {\n        var self = this;\n        FB.api('4', function(res) {\n            if(!res || res.error) {\n                self(new Error('Error occured'));\n            } else {\n                self(null, res);\n            }\n        });\n    },\n    function processResult(err, res) {\n        if(err) throw err;\n        console.log(res);\n    }\n);\n```\n\n### FB.napi with Step\n\nSimplified version of facebook-node-sdk async callbacks using `FB.napi`.\n\n```js\nvar FB      = require('fb').default,\n    Step    = require('step');\n\nStep(\n    function getUser() {\n        FB.napi('4', this);\n    },\n    function processResult(err, res) {\n        if(err) throw err;\n        console.log(res);\n    }\n);\n```\n\n## License\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnode-facebook%2Ffacebook-node-sdk.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnode-facebook%2Ffacebook-node-sdk?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnode-facebook%2Ffacebook-node-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnode-facebook%2Ffacebook-node-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnode-facebook%2Ffacebook-node-sdk/lists"}