Flame Blog
How to manually trigger Cloud Tasks in the emulator
Publishing Cloud Tasks to the emulator via the HTTP API.
Published April 24, 2026
By Val
When you define task queue handlers in your Firebase Functions, a matching task queue is automatically created in the emulator.
export const taskQueueFunction = functions.tasks.onTaskDispatched(
{
retryConfig: {
maxAttempts: 5,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 6,
},
},
async request => {
console.log({ data: request.data })
}
) export const taskQueueFunction = functions.tasks
.taskQueue({
retryConfig: {
maxAttempts: 5,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 6,
},
})
.onDispatch(async data => {
console.log({ data })
}) The Cloud Tasks emulator runs by default on port 9499 and you can push tasks
to it using the SDK:
import { initializeApp } from 'firebase-admin/app'
import { getFunctions } from 'firebase-admin/functions'
// Can also use `GOOGLE_CLOUD_PROJECT` environment variable
initializeApp({ projectId: 'my-project' })
process.env.CLOUD_TASKS_EMULATOR_HOST = 'localhost:9499'
const queue = getFunctions().taskQueue('taskQueueFunction')
await queue.enqueue(data)
But in this post I want to get into the details and show how to create tasks directly using the emulator’s HTTP API.
Creating a task
To push a task onto a queue manually, POST to the emulator’s tasks endpoint:
curl -X POST 'http://localhost:9499/projects/my-project/locations/us-central1/queues/taskQueueFunction/tasks' \
-H 'Content-Type: application/json' \
-d '{
"task": {
"httpRequest": {
"httpMethod": "POST",
"url": "http://localhost:5001/my-project/us-central1/taskQueueFunction",
"body": "eyJkYXRhIjp7ImZvbyI6ImJhciJ9fQ==",
"headers": {
"Content-Type": "application/json"
}
}
}
}'
The queue is not directly linked to the function, so we need to be explicit about the URL to the functions emulator to dispatch the task to.
The body field inside httpRequest is Base64-encoded and the actual
payload needs to be inside a data field. In this example we’re passing
{"data": {"foo": "bar"}}.
Buffer.from(JSON.stringify({ data: { foo: 'bar' } })).toString('base64')
// 'eyJkYXRhIjp7ImZvbyI6ImJhciJ9fQ=='
We can inline the Base64 encoding in the command for convenience:
curl -X POST 'http://localhost:9499/projects/my-project/locations/us-central1/queues/taskQueueFunction/tasks' \
-H 'Content-Type: application/json' \
-d '{
"task": {
"httpRequest": {
"httpMethod": "POST",
"url": "http://localhost:5001/my-project/us-central1/taskQueueFunction",
"body": "'$(echo '{"data": {"foo": "bar"}}' | base64)'",
"headers": {
"Content-Type": "application/json"
}
}
}
}'
The emulator will then dispatch the task to your function just as it would in production, with retries and all.
Calling the function directly
Since the Task Queue emulator just forwards the HTTP request to the functions emulator, you can also call the function directly. In the above example that would be (from our guide to calling Firebase emulator functions):
curl -X POST 'http://localhost:5001/my-project/us-central1/taskQueueFunction' \
-H 'Content-Type: application/json' \
-d '{"data": {"foo": "bar"}}'
You won’t get the retry behavior but it’s faster and you don’t need the Cloud Tasks API overhead.
Flame: the missing UI for the emulator ✨
Did you ever wish that localhost:4000 had an admin for the emulator queues and
functions?
This is why we built Flame, a Firebase emulator UI with everything that’s missing from the built-in admin.
No more guesswork with cURL commands, JSON protocols and Base64-encoding when debugging your queues, tasks and Firebase Functions. Just input your payload and send.
Also comes with an improved UI for Firebase Auth, Firestore, and more. Try it out!