{"id":13727850,"url":"https://github.com/draftbit/twitter-lite","last_synced_at":"2025-05-15T08:11:04.973Z","repository":{"id":29449634,"uuid":"121716902","full_name":"draftbit/twitter-lite","owner":"draftbit","description":"A tiny, full-featured, flexible client / server library for the Twitter API","archived":false,"fork":false,"pushed_at":"2023-03-04T13:52:45.000Z","size":1182,"stargazers_count":795,"open_issues_count":64,"forks_count":95,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-05-14T22:43:00.614Z","etag":null,"topics":["node","node-twitter","twitter","twitter-api","twitter-lite","twitter-rest","twitter-streams"],"latest_commit_sha":null,"homepage":"https://npm.im/twitter-lite","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/draftbit.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-16T05:07:44.000Z","updated_at":"2025-05-05T15:56:08.000Z","dependencies_parsed_at":"2024-06-18T12:24:56.357Z","dependency_job_id":"15655d6a-99ff-478a-8c8c-39b89db93839","html_url":"https://github.com/draftbit/twitter-lite","commit_stats":{"total_commits":123,"total_committers":25,"mean_commits":4.92,"dds":0.7154471544715447,"last_synced_commit":"00052e6b920e642a401f37b66972fd7b8553fa00"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftbit%2Ftwitter-lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftbit%2Ftwitter-lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftbit%2Ftwitter-lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftbit%2Ftwitter-lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/draftbit","download_url":"https://codeload.github.com/draftbit/twitter-lite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254301432,"owners_count":22047904,"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":["node","node-twitter","twitter","twitter-api","twitter-lite","twitter-rest","twitter-streams"],"created_at":"2024-08-03T02:00:33.924Z","updated_at":"2025-05-15T08:11:04.946Z","avatar_url":"https://github.com/draftbit.png","language":"JavaScript","funding_links":[],"categories":["Packages","JavaScript"],"sub_categories":["HTTP"],"readme":"# Twitter Lite\n\nA tiny, full-featured, modern client / server library for the [Twitter API](https://developer.twitter.com/en/docs/basics/things-every-developer-should-know).\n\n[![npm](https://img.shields.io/npm/v/twitter-lite.svg)](https://npm.im/twitter-lite) [![travis](https://travis-ci.org/draftbit/twitter-lite.svg?branch=master)](https://travis-ci.org/draftbit/twitter-lite)\n\n## Features\n\n- Promise driven via Async / Await\n- REST and Stream support\n- [Typescript support](https://github.com/draftbit/twitter-lite/blob/master/index.d.ts)\n- Works in Node.js\n- Rate limiting support\n- Under 1kb\n- Minimal dependencies\n- Test suite\n\n## Why\n\nWe have built this library because existing ones [have not been recently maintained](https://github.com/desmondmorris/node-twitter), or depend on [outdated](https://github.com/ttezel/twit/issues/411) [libraries](https://github.com/ttezel/twit/issues/412).\n\n## Installation\n\n```sh\nyarn add twitter-lite\n```\n\n```sh\nnpm install twitter-lite\n```\n\nThen you can include the following at the top of your code:\n\n```es6\nimport Twitter from 'twitter-lite';\n\nconst client = new Twitter({\n  ...\n})\n\nclient.get(...)\nclient.post(...)\n```\n\n## Usage\n\n- Create an app on [https://apps.twitter.com/](https://apps.twitter.com)\n- Grab the Consumer Key (API Key) and Consumer Secret (API Secret) from Keys and Access Tokens\n- Make sure you set the right access level for your app\n- If you want to use user-based authentication, grab the access token key and secret as well\n\n### App vs. User authentication\n\nTwitter has two different authentication options:\n\n- App: higher rate limits. Great for building your own Twitter App.\n- User: lower rate limits. Great for making requests on behalf of a User.\n\n**User** authentication requires:\n\n- `consumer_key`\n- `consumer_secret`\n- `access_token_key`\n- `access_token_secret`\n\n**App** authentication requires:\n\n- `bearer_token`\n\nApp authentication is a simple header behind the scenes:\n\n```es6\nheaders: {\n  Authorization: `Bearer ${bearer_token}`;\n}\n```\n\nYou can get the bearer token by calling `.getBearerToken()`.\n\n### Verifying credentials example (user auth)\n\n```es6\nconst client = new Twitter({\n  subdomain: \"api\", // \"api\" is the default (change for other subdomains)\n  version: \"1.1\", // version \"1.1\" is the default (change for other subdomains)\n  consumer_key: \"abc\", // from Twitter.\n  consumer_secret: \"def\", // from Twitter.\n  access_token_key: \"uvw\", // from your User (oauth_token)\n  access_token_secret: \"xyz\" // from your User (oauth_token_secret)\n});\n\nclient\n  .get(\"account/verify_credentials\")\n  .then(results =\u003e {\n    console.log(\"results\", results);\n  })\n  .catch(console.error);\n```\n\n### App authentication example\n\n```es6\nconst user = new Twitter({\n  consumer_key: \"abc\",\n  consumer_secret: \"def\"\n});\n\nconst response = await user.getBearerToken();\nconst app = new Twitter({\n  bearer_token: response.access_token\n});\n```\n\n### Oauth authentication\n\nAccording to the [docs](https://developer.twitter.com/en/docs/basics/authentication/api-reference/authenticate) this helps you get access token from your users.\n\n- [Request Token documentation](https://developer.twitter.com/en/docs/basics/authentication/api-reference/request_token)\n- [Access Token documentation](https://developer.twitter.com/en/docs/basics/authentication/api-reference/access_token)\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\",\n  consumer_secret: \"xyz\"\n});\n\nclient\n  .getRequestToken(\"http://callbackurl.com\")\n  .then(res =\u003e\n    console.log({\n      reqTkn: res.oauth_token,\n      reqTknSecret: res.oauth_token_secret\n    })\n  )\n  .catch(console.error);\n```\n\nThen you redirect your user to `https://api.twitter.com/oauth/authenticate?oauth_token=xyz123abc`, and once you get the verifier and the token, you pass them on to the [next stage of the authentication](https://developer.twitter.com/en/docs/basics/authentication/api-reference/access_token).\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\",\n  consumer_secret: \"xyz\"\n});\n\nclient\n  .getAccessToken({\n    oauth_verifier: oauthVerifier,\n    oauth_token: oauthToken\n  })\n  .then(res =\u003e\n    console.log({\n      accTkn: res.oauth_token,\n      accTknSecret: res.oauth_token_secret,\n      userId: res.user_id,\n      screenName: res.screen_name\n    })\n  )\n  .catch(console.error);\n```\n\nAnd this will return you your `access_token` and `access_token_secret`.\n\n### Tweeting a thread\n\n- [statuses/update documentation](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update)\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\",\n  consumer_secret: \"xyz\",\n  access_token_key: \"xyz\",\n  access_token_secret: \"xyz\"\n});\n\nasync function tweetThread(thread) {\n  let lastTweetID = \"\";\n  for (const status of thread) {\n    const tweet = await client.post(\"statuses/update\", {\n      status: status,\n      in_reply_to_status_id: lastTweetID,\n      auto_populate_reply_metadata: true\n    });\n    lastTweetID = tweet.id_str;\n  }\n}\n\nconst thread = [\"First tweet\", \"Second tweet\", \"Third tweet\"];\ntweetThread(thread).catch(console.error);\n```\n\n## Streams\n\nTo learn more about the streaming API visit the [Twitter Docs](https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter.html). The streaming API works only in Node.\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\" // from Twitter.\n  consumer_secret: \"xyz\" // from Twitter.\n  access_token_key: \"abc\" // from your User (oauth_token)\n  access_token_secret: \"abc\" // from your User (oauth_token_secret)\n});\n\nconst parameters = {\n  track: \"#bitcoin,#litecoin,#monero\",\n  follow: \"422297024,873788249839370240\",  // @OrchardAI, @tylerbuchea\n  locations: \"-122.75,36.8,-121.75,37.8\",  // Bounding box -\tSan Francisco\n};\n\nconst stream = client.stream(\"statuses/filter\", parameters)\n  .on(\"start\", response =\u003e console.log(\"start\"))\n  .on(\"data\", tweet =\u003e console.log(\"data\", tweet.text))\n  .on(\"ping\", () =\u003e console.log(\"ping\"))\n  .on(\"error\", error =\u003e console.log(\"error\", error))\n  .on(\"end\", response =\u003e console.log(\"end\"));\n\n// To stop the stream:\nprocess.nextTick(() =\u003e stream.destroy());  // emits \"end\" and \"error\" events\n```\n\nTo stop a stream, call `stream.destroy()`. That might take a while though, if the stream receives a lot of traffic. Also, if you attempt to destroy a stream from an `on` handler, you _may_ get an error about writing to a destroyed stream.\nIn that case, try to [defer](https://stackoverflow.com/questions/49804108/write-after-end-stream-error/53878933#53878933) the `destroy()` call:\n\n```es6\nprocess.nextTick(() =\u003e stream.destroy());\n```\n\nAfter calling `stream.destroy()`, you can recreate the stream, if you wait long enough - see the \"should reuse stream N times\" test. Note that Twitter may return a \"420 Enhance your calm\" error if you switch streams too fast. There are no response headers specifying how long to wait, and [the error](https://stackoverflow.com/questions/13438965/avoid-420s-with-streaming-api), as well as [streaming limits](https://stackoverflow.com/questions/34962677/twitter-streaming-api-limits) in general, are poorly documented. Trial and error has shown that for tracked keywords, waiting 20 to 30 seconds between re-creating streams was enough. Remember to also set up the `.on()` handlers again for the new stream.\n\n## Support for Twitter API v2\n\nThe new Twitter API v2 no longer requires the `.json` extension on its endpoints. In order to use `v2`, set `version: '2'` and `extension: false`.\n\n```es6\nconst client = new Twitter({\n  version: \"2\", // version \"1.1\" is the default (change for v2)\n  extension: false, // true is the default (this must be set to false for v2 endpoints)\n  consumer_key: \"abc\", // from Twitter.\n  consumer_secret: \"def\", // from Twitter.\n  access_token_key: \"uvw\", // from your User (oauth_token)\n  access_token_secret: \"xyz\" // from your User (oauth_token_secret)\n});\n```\n\n## Methods\n\n### .get(endpoint, parameters)\n\nReturns a Promise resolving to the API response object, or rejecting on error. The response and error objects also contain the HTTP response code and [headers](https://developer.twitter.com/en/docs/basics/rate-limiting.html), under the `_headers` key. These are useful to check for [rate limit](#rate-limiting) information.\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\",\n  consumer_secret: \"xyz\",\n  access_token_key: \"abc\",\n  access_token_secret: \"abc\"\n});\n\nconst rateLimits = await client.get(\"statuses/show\", {\n  id: \"1016078154497048576\"\n});\n```\n\n### .post(endpoint, parameters)\n\nSame return as `.get()`.\n\nUse the `.post` method for actions that change state, or when the total size of the parameters might be too long for a GET request. For [example](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create.html), to follow a user:\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\",\n  consumer_secret: \"xyz\",\n  access_token_key: \"abc\",\n  access_token_secret: \"abc\"\n});\n\nawait client.post(\"friendships/create\", {\n  screen_name: \"dandv\"\n});\n```\n\nThe second use case for POST is when you need to pass more parameters than suitable for the length of a URL, such as when [looking up a larger number of user ids or screen names](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup):\n\n```es6\nconst users = await client.post(\"users/lookup\", {\n  screen_name: \"longScreenName1,longerScreeName2,...,veryLongScreenName100\"\n});\n```\n\n### .put(endpoint, query_parameters, request_body)\n\nSame return as `.get()` and `.post()`.\n\nUse the `.put` method for actions that update state. For [example](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/update-welcome-message), to update a welcome message.\n\n```es6\nconst client = new Twitter({\n  consumer_key: \"xyz\",\n  consumer_secret: \"xyz\",\n  access_token_key: \"abc\",\n  access_token_secret: \"abc\"\n});\n\nconst welcomeMessageID = \"abc\";\n\nawait client.put(\n  \"direct_messages/welcome_messages/update\",\n  {\n    id: welcomeMessageID\n  },\n  {\n    message_data: {\n      text: \"Welcome!!!\"\n    }\n  }\n);\n```\n\n### .getBearerToken()\n\nSee the [app authentication example](#app-authentication-example).\n\n### .getRequestToken(twitterCallbackUrl)\n\nSee the [OAuth example](#oauth-authentication).\n\n### .getAccessToken(options)\n\nSee the [OAuth example](#oauth-authentication).\n\n## Examples\n\nYou can find many more examples for various resources/endpoints in [the tests](test).\n\n## Troubleshooting\n\n### Headers on success\n\n```es6\nconst tweets = await client.get(\"statuses/home_timeline\");\nconsole.log(`Rate: ${tweets._headers.get('x-rate-limit-remaining')} / ${tweets._headers.get('x-rate-limit-limit')}`);\nconst delta = (tweets._headers.get('x-rate-limit-reset') * 1000) - Date.now()\nconsole.log(`Reset: ${Math.ceil(delta / 1000 / 60)} minutes`);\n```\n\n### API errors\n\n`.get` and `.post` reject on error, so you can use try/catch to handle errors. The error object contains an `errors` property with the error `code` and `message`, and a `_headers` property with the the HTTP response code and [Headers](https://developer.twitter.com/en/docs/basics/rate-limiting.html) object returned by the Twitter API.\n\n```es6\ntry {\n  const response = await client.get(\"some/endpoint\");\n  // ... use response here ...\n} catch (e) {\n  if ('errors' in e) {\n    // Twitter API error\n    if (e.errors[0].code === 88)\n      // rate limit exceeded\n      console.log(\"Rate limit will reset on\", new Date(e._headers.get(\"x-rate-limit-reset\") * 1000));\n    else\n      // some other kind of error, e.g. read-only API trying to POST\n  } else {\n    // non-API error, e.g. network problem or invalid JSON in response\n  }\n}\n```\n\n#### Rate limiting\n\nA particular case of errors is exceeding the [rate limits](https://developer.twitter.com/en/docs/basics/rate-limits.html). See the example immediately above for detecting rate limit errors, and read [Twitter's documentation on rate limiting](https://developer.twitter.com/en/docs/basics/rate-limiting.html).\n\n### Numeric vs. string IDs\n\nTwitter uses [numeric IDs](https://developer.twitter.com/en/docs/basics/twitter-ids.html) that in practice can be up to 18 characters long. Due to rounding errors, it's [unsafe to use numeric IDs in JavaScript](https://developer.twitter.com/en/docs/basics/things-every-developer-should-know). Always set `stringify_ids: true` when possible, so that Twitter will return strings instead of numbers, and rely on the `id_str` field, rather than on the `id` field.\n\n## Contributing\n\nWith the library nearing v1.0, contributions are welcome! Areas especially in need of help involve multimedia (see [#33](https://github.com/draftbit/twitter-lite/issues/33) for example), and adding tests (see [these](https://github.com/ttezel/twit/tree/master/tests) for reference).\n\n### Development\n\n1.  Fork/clone the repo\n2.  `yarn/npm install`\n3.  Go to \u003chttps://apps.twitter.com\u003e and create an app for testing this module. Make sure it has read/write permissions.\n4.  Grab the consumer key/secret, and the access token/secret and place them in a [.env](https://www.npmjs.com/package/dotenv) file in the project's root directory, under the following variables:\n    ```\n    TWITTER_CONSUMER_KEY=...\n    TWITTER_CONSUMER_SECRET=...\n    ACCESS_TOKEN=...\n    ACCESS_TOKEN_SECRET=...\n    ```\n5.  `yarn/npm test` and make sure all tests pass\n6.  Add your contribution, along with test case(s). Note: feel free to skip the [\"should DM user\"](https://github.com/draftbit/twitter-lite/blob/34e8dbb3efb9a45564275f16473af59dbc4409e5/twitter.test.js#L167) test during development by changing that `it()` call to `it.skip()`, but remember to revert that change before committing. This will prevent your account from being flagged as [abusing the API to send too many DMs](https://github.com/draftbit/twitter-lite/commit/5ee2ce4232faa07453ea2f0b4d63ee7a6d119ce7).\n7.  Make sure all tests pass. **NOTE: tests will take over 10 minutes to finish.**\n8.  Commit using a [descriptive message](https://chris.beams.io/posts/git-commit/) (please squash commits into one per fix/improvement!)\n9.  `git push` and submit your PR!\n\n## Credits\n\nAuthors:\n\n- [@dandv](https://github.com/dandv)\n- [@peterpme](https://github.com/peterpme)\n\nOver the years, thanks to:\n\n- [@ttezel](https://github.com/ttezel)\n- [@technoweenie](http://github.com/technoweenie)\n- [@jdub](http://github.com/jdub)\n- [@desmondmorris](http://github.com/desmondmorris)\n- [Node Twitter\n  Community](https://github.com/desmondmorris/node-twitter/graphs/contributors)\n- [@dylanirlbeck](https://github.com/dylanirlbeck)\n- [@Fdebijl](https://github.com/Fdebijl) - Typescript support\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdraftbit%2Ftwitter-lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdraftbit%2Ftwitter-lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdraftbit%2Ftwitter-lite/lists"}