TweetScraperR recolecta datos de X/Twitter —tweets, usuarixs y
metadatos— para análisis y visualización en R, sin usar la API oficial
de pago. Desde la versión 0.4.0, el scraping corre sobre un motor de
Node.js + Playwright y consulta la API GraphQL interna de X,
devolviendo datos estructurados desde JSON: texto completo (sin
truncar), fecha exacta, métricas (respuestas, retweets, citas, me gusta,
vistas), media, hashtags y menciones. La autenticación se hace importando
la sesión real de tu navegador (cookies), ya que X bloquea el login
automatizado. Es una alternativa flexible, gratuita y de código abierto.
TweetScraperR collects data from X/Twitter —tweets, users and
metadata— for analysis and visualization in R, without using the paid
official API. Since version 0.4.0, scraping runs on a Node.js +
Playwright engine and queries X's internal GraphQL API, returning
structured data from JSON: full text, exact date, metrics, media,
hashtags and mentions. Authentication works by importing your real
browser session (cookies), since X blocks automated login. It is a
flexible, free, and open-source alternative.
Puedes instalar la versión de desarrollo de TweetScraperR desde GitHub con:
# install.packages("devtools")
devtools::install_github("agusnieto77/TweetScraperR")- Node.js (>= 18): el motor de scraping está basado en Node.js +
Playwright + stealth. Se instala una sola vez con
installPlaywrightEngine()(ver más abajo). - Chrome o Chromium: navegador basado en Chromium requerido por el motor de Playwright.
- Cuenta de X/Twitter: necesaria para las funciones que requieren autenticación.
- Variables de entorno:
OPENAI_API_KEY: opcional, solo para las funciones de análisis (getTweetsSentiments()ygetTweetsImagesAnalysis()).XQUIK_API_KEY: opcional, solo paragetTweetsXquikSearch().
Nota: las variables
TWITTER_USER/TWITTER_PASS(y su fallback legacyUSER/PASS) y el login automatizado quedaron deprecados: X bloquea el login por automatización. La autenticación ahora se realiza importando la sesión real del navegador conimportSessionX()(ver la sección Autenticación).
Más detalles en Requisitos.md.
El scraping ya no usa chromote: corre sobre un motor de Node.js +
Playwright + stealth.
- Necesitás Node.js (>= 18) instalado en tu sistema.
- Una sola vez, después de instalar el paquete, ejecutá:
library(TweetScraperR)
# Instala el motor de Node.js/Playwright (una sola vez)
installPlaywrightEngine()
# Verifica que el motor esté instalado y operativo
checkPlaywrightEngine()X bloquea el login automatizado, por lo que ya no es viable iniciar sesión desde R con usuario y contraseña. En su lugar, se importa la sesión real de tu navegador y se reutiliza para todas las funciones de scraping. El flujo es:
- Logueate a mano en X/Twitter desde tu navegador normal (por ejemplo, Chrome).
- Copiá las cookies
auth_tokenyct0del dominiox.com. Abrí las herramientas de desarrollo (DevTools,F12) → pestaña Application (o Storage) → Cookies →https://x.com, y copiá los valores deauth_tokenyct0. - Importá la sesión en R con
importSessionX():
library(TweetScraperR)
importSessionX(
auth_token = "TU_AUTH_TOKEN",
ct0 = "TU_CT0"
)A partir de ese momento, todas las funciones de scraping reutilizan esa
sesión (persistida como storageState) sin necesidad de volver a loguearte.
Las cookies expiran. Cuando la sesión deje de funcionar, volvé a copiar
auth_tokenyct0desde el navegador y reimportalas conimportSessionX().
La vía recomendada es la familia de funciones *API(): consultan la
API GraphQL interna de X y devuelven datos estructurados directamente del
JSON (texto completo sin truncar, fecha exacta y métricas: respuestas,
retweets, citas, me gusta y vistas), sin selectores CSS frágiles. Todas reusan
la sesión importada con importSessionX(). Las funciones de scraping por HTML
siguen disponibles pero quedaron deprecadas en favor de estas.
| Función | Qué recupera |
|---|---|
getUserTweetsAPI() |
Timeline de unx usuarix |
getTweetsTimelinesAPI() |
Timeline combinado de varias cuentas |
getTweetsSearchAPI() |
Búsqueda (product = "Latest"/"Top"/"Media") |
getTweetsRepliesAPI() |
Tweet y sus respuestas (hilo) |
getTweetsDataAPI() |
Datos de tweets a partir de sus URLs |
getUserMediaAPI() |
Tweets con media (fotos/videos) de unx usuarix |
getTweetsRetweetsAPI() |
Usuarixs que repostearon un tweet |
getUserFollowersAPI() |
Seguidorxs de unx usuarix |
getUserFollowingAPI() |
Cuentas que sigue unx usuarix |
getUsersDataAPI() |
Datos de perfil de usuarixs |
Las funciones de tweets devuelven un tibble rico: texto completo, fecha,
idioma, métricas (respuestas/retweets/citas/me gusta/vistas), y list-columns
media, hashtags, menciones, urls_externas y emoticones — listo para
analizar con plotTime(), plotWords(), plotEmojis() o getTweetsSentiments().
library(TweetScraperR)
importSessionX(auth_token = "tu_auth_token", ct0 = "tu_ct0")
tw <- getTweetsSearchAPI("#RStats", n_tweets = 100, product = "Latest")- El scraping autenticado de X/Twitter puede violar sus Términos de Servicio y derivar en la suspensión de la cuenta utilizada. Usalo bajo tu propia responsabilidad.
- El contenido recolectado está sujeto a los derechos de X/Twitter y de lxs autorxs de los tweets; su almacenamiento y redistribución pueden estar limitados por esos derechos y por la normativa de protección de datos aplicable.
getTweetsSentiments()ygetTweetsImagesAnalysis()envían los datos recolectados (textos e imágenes de terceros) a la API de OpenAI.- Se recomienda usar una cuenta dedicada de investigación (no tu cuenta personal) y respetar los marcos éticos de investigación de tu institución.
El listado completo de funciones, organizado por categoría y con su estado de ciclo de vida, está en la referencia del sitio de documentación:
👉 https://agusnieto77.github.io/TweetScraperR/reference/
Las recomendadas son la familia *API() (ver la tabla de arriba). Las
funciones de scraping por HTML (getTweetsTimeline(),
getTweetsHistoricalSearch(), getTweetsData(), getUsersData(), la
familia getUrls*(), las variantes *For(), etc.) quedaron deprecadas
en favor de sus equivalentes *API(); siguen funcionando con una
advertencia de ciclo de vida.
require(TweetScraperR)
# 1) Importás tu sesión UNA vez (cookies auth_token y ct0 del navegador)
importSessionX(auth_token = "TU_AUTH_TOKEN", ct0 = "TU_CT0")
# 2) Búsqueda: tweets recientes que mencionan un hashtag
tweets <- getTweetsSearchAPI("#RStats", n_tweets = 100, product = "Latest")
# 3) Timeline de una cuenta
timeline <- getUserTweetsAPI("rstatstweet", n_tweets = 200)
# 4) Timeline COMBINADO de varias cuentas (curaduría de investigación)
combinado <- getTweetsTimelinesAPI(
c("elravignani", "NucleoIdaes", "BNMMArgentina"),
n_tweets = 100
)
# 5) Datos de perfil de usuarixs
perfiles <- getUsersDataAPI(c("NASA", "rstatstweet"))Cada función de tweets devuelve un tibble con datos estructurados
(21 columnas), listo para analizar:
dplyr::glimpse(tweets)
#> Rows: 100
#> Columns: 21
#> $ fecha <dttm> 2026-06-13 21:42:13, 2026-06-13 12:10:47, ...
#> $ user <chr> "@RosanaFerrero", "@aRtsy_package", ...
#> $ texto <chr> "...texto completo, sin truncar..."
#> $ idioma <chr> "es", "en", ...
#> $ megustas <int> 7203, 0, 8221, ...
#> $ retweets <int> 1194, 323, 1465, ...
#> $ views <int> 470857, 34, 378665, ...
#> $ media <list> ["https://pbs.twimg.com/media/...jpg"], [], ...
#> $ hashtags <list> ["RStats"], [], ...
#> $ menciones <list> ["Space_Station", "SpaceX"], [], ...
#> $ urls_externas <list> ["https://go.nasa.gov/..."], [], ...
#> $ emoticones <list> ["✈"], [], ...
#> # ... respuestas, citas, es_retweet, es_cita, tweet_citado_id,
#> # media_tipo, conversation_id, url, tweet_idY analizás/visualizás directo, sin renombrar columnas:
plotTime(tweets) # serie temporal (columna fecha)
plotWords(tweets) # nube de palabras (columna texto)
plotEmojis(tweets) # ranking de emojis (columna emoticones)
getTweetsSentiments(tweets$texto) # análisis de sentimiento (vía OpenAI)