Even after posting about the coolest AI tools every day on X.com (Twitter), my follower count is sill the same. And yeah, even you don’t follow me there—no hard feelings. But still, I couldn’t just ghost the platform. Because let’s be honest: consistency is the key, and I am here for the long game. So last week, I cracked. I wrote some JavaScript, connected a few free API keys, and boom: created a fully automated Twitter bot.

One post on X (formerly Twitter) every day, about a new AI tool with hashtags and emojis. Yeah, that’s what we’re going to build today. I’ll walk you through how to fully automate your X (Twitter) account using free API keys and JavaScript.
Why This Automation Rocks
- No cost: Use generous free tier API keys.
- Human tone: Tweets sound natural and fun (no robotic text).
- Easy setup: No backend required, no database, just a simple Node.js script.
- Fully customizable: Change prompts, style, or even API providers.
How It Works
- We program a function that sends prompts to an AI API (like Perplexity, Gemini, DeepSeek) to generate tweets about new AI tools.
- We randomize prompt templates so tweets stay fresh and lively.
- We post the AI-generated tweet to X using the official Twitter API.
- The script runs fully automatically.
Step 1: Set Up to Run Your Code
- Save all the project files in one folder, e.g., ai-twitter-bot.
- Use any code editor you like: Visual Studio Code, Sublime Text, Notepad++, etc.
- Initialize Node.js project with: npm init -y (before writing the scripts)
- Install Twitter API client: npm install twitter-api-v2 node-fetch (either before or after writing the scripts)
- Run your script with: node twitterBot.js (of course, after, I mean, what else are you planning to run? Your dreams?)
But hey, where are the scripts? Yes, yes, I will show them to you right now.
Step 2: The AI Call Function Using Perplexity API
For the first script, create a file callPerplexity.js with this code:
const fetch = require('node-fetch');
async function callPerplexity({
prompt,
apiKey = "Your-api-key", // If you have
model = "sonar-pro",
temperature = 0.3,
maxTokens = 1500,
apiUrl = "https://api.perplexity.ai/chat/completions",
systemExtra = ""
}) {
if (!prompt) {
throw new Error("Missing required parameter: prompt.");
}
const baseWritingRules = `Keep the tone natural, friendly, and human.`; // You can add multiple rules here
const systemPrompt = `${baseWritingRules}\n\n${systemExtra}`.trim();
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model,
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: prompt }
],
temperature,
max_tokens: maxTokens
})
});
if (!response.ok) {
throw new Error(`Perplexity API error: ${response.status} ${response.statusText}`);
}
const json = await response.json();
if (!json.choices?.[0]?.message?.content) {
throw new Error("Invalid response from Perplexity API.");
}
return cleanResponse(json.choices[0].message.content.trim());
// --- Cleaner: Removes markdown, citations, junk characters, unsafe tags ---
function cleanResponse(text) {
return text
.replace(/\[\d+\]/g, '') // Remove citations like [1]
.replace(/\[(.*?)\]\((.*?)\)/g, '$1') // Markdown links
.replace(/`([^`]+)`/g, '$1') // Inline code
.replace(/\*\*(.*?)\*\*/g, '$1') // Bold markdown
.replace(/<\/?code>/gi, '') // <code> tags
.replace(/<br\s*\/?>/gi, '\n') // <br> to newlines
.replace(/<\/?[^>]+(>|$)/g, match => {
return /<(strong|b|i|em|u|p|h\d)>/i.test(match) ? match : '';
})
.replace(/ /g, ' ') // Non-breaking spaces
.replace(/[^\x20-\x7E\n\r]+/g, '') // Junk characters
.replace(/\s{2,}/g, ' ') // Extra spaces
.trim();
}
}
module.exports = { callPerplexity };
If you don’t have Perplexity Pro, I can relate, I am broke too. Later, I will tell you how to get free AI API keys, hold on.
Step 3: Twitter Bot Code to Post Tweets
Now, for second script, create twitterBot.js to use the above AI call and Twitter API:
const { TwitterApi } = require('twitter-api-v2');
const { callPerplexity } = require('./callPerplexity');
// Twitter client with free developer keys – replace with your own once created
const twitterClient = new TwitterApi({
appKey: 'YOUR_APP_KEY_HERE',
appSecret: 'YOUR_APP_SECRET_HERE',
accessToken: 'YOUR_ACCESS_TOKEN_HERE',
accessSecret: 'YOUR_ACCESS_SECRET_HERE'
});
// Prompt templates to keep tweets varied and engaging
const promptTemplates = [
"Tell me about a newly launched AI tool today. Write a tweet that sounds like a dev sharing it casually on X. Keep it fun, witty, and human.",
"What’s a fresh AI tool that launched today? Summarize it like a founder tweeting about their product, with slight humour and real use case.",
"Write a tweet about the most interesting AI tool launched today. Add a playful tone like a tech bro who actually knows what he's saying.",
"Pretend you're an indie hacker discovering a cool AI tool released today. Share it like a tweet with one emoji and a smart insight.",
"Write a tweet highlighting today’s most useful new AI tool. Keep it human, a bit cheeky, and avoid sounding robotic or too serious."
];
// Pick a random prompt template
function getRandomPrompt() {
const index = Math.floor(Math.random() * promptTemplates.length);
return promptTemplates[index];
}
// Main function to generate and post tweet
async function postToX() {
try {
const dynamicPrompt = getRandomPrompt();
const tweetContent = await callPerplexity({
prompt: dynamicPrompt,
maxTokens: 240,
temperature: 0.5,
systemExtra: `
You are writing a tweet under 250 characters.
Keep it human, witty, and non-robotic.
Use light humour, avoid contractions, no markdown or links.
One or two emojis max, and a bit of curiosity or surprise at the end.
Avoid sounding too formal or promotional.
`
});
const tweetResponse = await twitterClient.v2.tweet(tweetContent);
console.log("Tweet posted:", tweetContent);
return tweetResponse;
} catch (err) {
console.error("Tweet failed:", err.message);
}
}
// Run the bot once
postToX();
Alternate 1: Using Free Google Gemini API Instead
If you don’t have Perplexity access, switch to Gemini:
- Get a free API key from Google AI Studio (Need a step-by-step guide? Click here)
- Replace callPerplexity with this callGemini function:
const fetch = require('node-fetch');
async function callGemini({ prompt, apiKey }) {
if (!prompt) throw new Error("Missing prompt.");
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: [{ parts: [{ text: prompt }] }]
})
});
const data = await response.json();
return data.candidates?.[0]?.content?.parts?.[0]?.text || "No output received.";
}
module.exports = { callGemini };
You then update your twitter bot to call callGemini({ prompt, apiKey: ‘YOUR_GEMINI_API_KEY’ }) instead.
Alternate 2: Using Free DeepSeek AI API via OpenRouter
Alternatively, try DeepSeek free via OpenRouter.ai:
- Create an account and get a free API key (Wrote a full article on this as well, click here to check it out)
- Use this function to call DeepSeek:
const fetch = require('node-fetch');
async function callDeepSeek({ prompt, apiKey }) {
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "deepseek/deepseek-r1-0528:free",
messages: [{ role: "user", content: prompt }]
})
});
const data = await response.json();
return data.choices?.[0]?.message?.content || "No reply received.";
}
module.exports = { callDeepSeek };
Then like before, change your twitter bot code to use this function for content generation. All set.
Bye Bye Message
So yes, it’s that simple. Just make sure to always keep your API keys safe: never put real API keys in a public repository. Now go have fun customising the prompts and explore the power of AI on social media.
