The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Twitter/X Scraping for R via Python’s twscrape
twscrape sin instalar software automáticamentetwscrape: Usa la librería
Python twscrape desde R mediante
reticulatetwscrape# Instalar desde GitHub
library(devtools)
install_github("agusnieto77/twscrapeR")Requisito importante del entorno Python: usá
twscrape >= 0.18.0 con Python >= 3.10. La versión
twscrape 0.17.0 quedó rota para SearchTimeline
después de cambios en X/Twitter y puede fallar con
IndexError: list index out of range. Desde
twscrape 0.18.0, el fix viene upstream y
twscrapeR ya no necesita aplicar un monkeypatch local.
Instalá o actualizá twscrape fuera de las funciones del
paquete, por ejemplo en una terminal:
python -m pip install "twscrape>=0.18.0"library(twscrapeR)
# Configuración guiada (solo verifica el entorno; no instala software)
setup_twscraper()La función setup_twscraper() te guiará a través de: 1.
Detección de Python >= 3.10 2. Verificación de la librería Python
twscrape 3. Configuración del entorno
Si no tenés Python o twscrape
instalado, setup_twscraper() mostrará
instrucciones para instalarlo manualmente fuera de R.
Opción recomendada: guardá tus credenciales en .Renviron
y agregá la cuenta sin escribir secretos en el script.
# En .Renviron
TWS_USERNAME='tu_usuario'
TWS_PASSWORD='tu_password'
TWS_EMAIL='tu@email.com'
TWS_EMAIL_PASSWORD='email_pass'
# Opción A: cookie completa
TWS_COOKIES='auth_token=valor_auth_token; ct0=valor_ct0'
# Opción B: valores separados; add_account_from_env() arma la cookie
TWS_AUTH_TOKEN='valor_auth_token'
TWS_CT0='valor_ct0'
# En R
add_account_from_env()Para varias cuentas podés repetir el esquema con otro prefijo y
pasarlo a la función, por ejemplo TWS2_USERNAME,
TWS2_PASSWORD, TWS2_COOKIES, etc. y luego
add_account_from_env(prefix = "TWS2_").
También podés pasar todo explícitamente:
add_account(
username = "tu_usuario",
password = "tu_password",
email = "tu@email.com",
email_password = "email_pass",
cookies = "auth_token=...; ct0=..."
)Nota IMPORTANTE: Las cookies son
OBLIGATORIAS para que la cuenta se active
correctamente. Podés pasarlas como TWS_COOKIES o como
TWS_AUTH_TOKEN + TWS_CT0.
auth_token y ct0"auth_token=valor1; ct0=valor2"# Buscar tweets
tweets <- search_tweets("rstats", n = 100)
# Por defecto busca Latest; para tweets destacados/populares usá Top
top_tweets <- search_tweets("rstats", n = 100, product = "Top")
# Convertir a dataframe
df <- to_dataframe(tweets)
View(df)
# Guardar
save_csv(tweets, "tweets_rstats.csv")# Búsqueda general
tweets <- search_tweets("machine learning", n = 100)
# Latest es el valor por defecto; Top devuelve resultados destacados/populares
latest <- search_tweets("machine learning", n = 100, product = "Latest")
top <- search_tweets("machine learning", n = 100, product = "Top")
# Por hashtag
tweets <- search_hashtag("rstats", n = 50)
tweets <- search_hashtag("#datascience", n = 100) # Con o sin #
# Menciones de un usuario
mentions <- search_mentions("hadleywickham", n = 50)
# Búsquedas avanzadas
tweets <- search_tweets("rstats lang:en", n = 100) # Solo inglés
tweets <- search_tweets("from:hadleywickham", n = 50) # De un usuario específico# Obtener tweets de un usuario
tweets <- user_tweets("hadleywickham", n = 100)
# Ver información del usuario
user <- get_user("hadleywickham")
print(user)# Listar cuentas configuradas
list_accounts()
# Eliminar una cuenta
delete_account("usuario")# Convertir a dataframe
df <- to_dataframe(tweets)
# Guardar como CSV
save_csv(tweets, "tweets.csv")
# Guardar como JSON
save_json(tweets, "tweets.json")# Filtrar por idioma
tweets_es <- filter_by_lang(tweets, "es")
tweets_en <- filter_by_lang(tweets, "en")
# Filtrar por fecha
tweets_recent <- filter_by_date(tweets, from = "2025-10-01")
tweets_range <- filter_by_date(tweets, from = "2025-10-01", to = "2025-10-26")
# Ordenar por likes
top_tweets <- sort_tweets(tweets, by = "like_count")
# Ordenar por fecha (más recientes primero)
recent_first <- sort_tweets(tweets, by = "date", decreasing = TRUE)# Configuración inicial del sistema
setup_twscraper()
# Agregar cuenta - se activa automáticamente con cookies
add_account_from_env()
# O pasar los datos explícitamente
add_account(
username = "usuario",
password = "pass",
email = "email@example.com",
email_password = "email_pass",
cookies = "auth_token=...; ct0=..." # OBLIGATORIO
)
# Listar todas las cuentas configuradas (muestra estado activo/inactivo)
accounts <- list_accounts()
# Eliminar una cuenta
delete_account("usuario")
# Verificar configuración del sistema
check_setup()# Búsqueda general de tweets; product acepta "Latest" o "Top"
tweets <- search_tweets("machine learning", n = 100)
top_tweets <- search_tweets("machine learning", n = 100, product = "Top")
# Buscar por hashtag
tweets <- search_hashtag("rstats", n = 50)
tweets <- search_hashtag("#datascience", n = 100) # Con o sin #
# Buscar menciones a un usuario
mentions <- search_mentions("hadleywickham", n = 50)# Obtener tweets de un usuario
tweets <- user_tweets("rstudio", n = 100)
# Obtener tweets Y respuestas de un usuario
tweets_replies <- user_tweets_and_replies("hadleywickham", n = 100)
# Obtener solo tweets con media (imágenes/videos)
media_tweets <- user_media("NASA", n = 50)# Obtener información detallada de un usuario
user <- get_user("hadleywickham")
print(user$followers_count)
print(user$following_count)
print(user$description)# Obtener detalles completos de un tweet
tweet_id <- "1234567890123456789"
details <- tweet_details(tweet_id)
# Obtener respuestas a un tweet
replies <- tweet_replies(tweet_id, n = 50)
# Obtener quién retuiteó un tweet
retweeters <- get_retweeters(tweet_id, n = 100)
# Obtener retweeters para varios tweets
tweets <- search_tweets("rstats", n = 10)
retweeters <- get_retweeters_batch(tweets, n = 50)
retweeters_df <- to_dataframe(retweeters) # incluye source_tweet_id
# Si querés mantenerlos agrupados por tweet
retweeters_by_tweet <- get_retweeters_batch(tweets, n = 50, flatten = FALSE)# Obtener seguidores de un usuario
followers <- get_followers("rstudio", n = 100)
# Obtener a quién sigue un usuario
following <- get_following("hadleywickham", n = 100)
# Obtener solo seguidores verificados
verified <- verified_followers("elonmusk", n = 50)# Convertir tweets a dataframe
tweets <- search_tweets("rstats", n = 100)
df_tweets <- to_dataframe(tweets)
# También funciona con usuarios
followers <- get_followers("rstudio", n = 50)
df_users <- to_dataframe(followers)# Filtrar tweets por idioma
tweets_es <- filter_by_lang(tweets, "es")
tweets_en <- filter_by_lang(tweets, "en")
# Filtrar por fecha
tweets_recent <- filter_by_date(tweets, from = "2025-10-01")
tweets_range <- filter_by_date(
tweets,
from = "2025-10-01",
to = "2025-10-26"
)
# Ordenar tweets
top_tweets <- sort_tweets(tweets, by = "like_count")
recent_tweets <- sort_tweets(tweets, by = "date", decreasing = TRUE)# Guardar como CSV
save_csv(tweets, "tweets.csv")
# Guardar como JSON
save_json(tweets, "tweets.json")library(twscrapeR)
library(dplyr)
library(ggplot2)
# 1. Configurar
setup_twscraper()
add_account(...)
# 2. Buscar tweets
tweets <- search_tweets("#rstats", n = 1000)
# 3. Convertir a dataframe
df <- to_dataframe(tweets)
# 4. Análisis con dplyr
df %>%
filter(lang == "en") %>%
arrange(desc(like_count)) %>%
select(username, text, like_count, retweet_count) %>%
head(10)
# 5. Visualización
df %>%
count(date = as.Date(date)) %>%
ggplot(aes(date, n)) +
geom_line() +
labs(title = "Tweets sobre #rstats por día",
x = "Fecha", y = "Número de tweets")
# 6. Top usuarios
df %>%
count(username, sort = TRUE) %>%
head(10) %>%
ggplot(aes(reorder(username, n), n)) +
geom_col() +
coord_flip() +
labs(title = "Top 10 usuarios", x = "", y = "Tweets")Si setup_twscraper() no encuentra Python:
# Especificar ruta a Python ya instalado
setup_twscraper(python_path = "C:/Python/python.exe")Instalá Python 3.10+ manualmente desde https://www.python.org/downloads/ o con tu gestor de
entornos preferido. Después instalá twscrape en ese entorno
y ejecutá setup_twscraper() nuevamente.
# Verificar si todo está correcto
check_setup()
# Ver configuración de Python
reticulate::py_config()Si una cuenta aparece como active = FALSE:
# 1. Listar cuentas para ver el estado
list_accounts()
# 2. Eliminar la cuenta inactiva
delete_account("usuario")
# 3. Volver a agregarla CON cookies válidas y actuales
add_account(
username = "usuario",
password = "pass",
email = "email@example.com",
email_password = "email_pass",
cookies = "auth_token=...; ct0=..." # OBLIGATORIO
)Importante: - Las cookies son OBLIGATORIAS para activar cuentas - Si una cuenta no se activa, las cookies están expiradas o son inválidas - Obtén nuevas cookies desde tu navegador (ver sección “¿Cómo obtener cookies?”)
Twitter/X aplica límites por tipo de consulta y twscrape
los administra por cola. Si ves un mensaje como este:
No account available for queue "Followers". Next available at 20:25:08
significa que todas las cuentas disponibles para esa cola llegaron temporalmente a su límite. No es un error de R: hay que esperar o distribuir mejor la carga.
Qué hacer:
n: empezá con valores chicos
(n = 50 o n = 100) y subí de a poco.twscrape
rota automáticamente entre cuentas activas.list_accounts() y confirmá que aparezcan como
active = TRUE.Ejemplo con varias cuentas:
add_account("usuario1", "pass1", "email1@example.com", "email_pass1", "auth_token=...; ct0=...")
add_account("usuario2", "pass2", "email2@example.com", "email_pass2", "auth_token=...; ct0=...")
list_accounts()No hay un número universal que evite siempre el bloqueo: depende de
la cola (Search, Followers,
UserTweets, etc.), de la edad/estado de las cuentas y de la
carga reciente. La regla práctica es pedir lotes más chicos y dejar que
la rotación haga su trabajo.
IndexError: list index out of range en twscrapeX/Twitter cambia con frecuencia sus bundles web. En
twscrape 0.17.0 eso puede romper el cálculo interno de
x-client-transaction-id y bloquear consultas reales aunque
la cuenta figure activa.
La solución actual es usar twscrape >= 0.18.0, donde
el arreglo ya viene incluido upstream. twscrapeR no aplica
un monkeypatch local para este caso.
python -m pip install "twscrape>=0.18.0"setup_twscraper()Después de actualizar, una prueba corta como
search_tweets("Milei", n = 5) debería funcionar si la
cuenta y las cookies están activas.
tweet <- tweets[[1]]
str(tweet)Campos disponibles: - id: ID del tweet -
date: Fecha y hora (POSIXct) - text: Texto
completo del tweet - username: Usuario que publicó -
user_displayname: Nombre mostrado del usuario -
user_id: ID del usuario - reply_count: Número
de respuestas - retweet_count: Número de retweets -
like_count: Número de likes - quote_count:
Número de quote tweets - views_count: Número de vistas -
lang: Idioma del tweet - url: URL del tweet -
user_followers: Seguidores del usuario -
user_verified: Usuario verificado (TRUE/FALSE)
user <- get_user("username")
str(user)Campos: - id: ID del usuario - username:
@usuario -
displayname: Nombre mostrado - description:
Biografía - followers_count: Seguidores -
following_count: Siguiendo - tweets_count:
Total de tweets - verified: Cuenta verificada -
created: Fecha de creación - location:
Ubicación - url: URL del perfil -
profile_image_url: URL de la foto de perfil
Las contribuciones son bienvenidas! Por favor:
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)MIT License - ver archivo LICENSE
twscrapeR es posible gracias a dos proyectos excepcionales de Python:
snscrape por JustAnotherArchivist: Arquitectura base de scraping, parsers y modelos de datos.
twscrape por vladkens: Sistema multi-cuenta, rate limiting y generación de X-Client-Transaction-ID.
Y al ecosistema de R:
Este paquete es para propósitos educativos y de investigación. Asegúrate de cumplir con los términos de servicio de Twitter/X al usarlo.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.