Skip to content

Instantly share code, notes, and snippets.

@BananaAcid
Last active January 24, 2026 17:59
Show Gist options
  • Select an option

  • Save BananaAcid/331cc3c073564f2cb5a831e04aef35e5 to your computer and use it in GitHub Desktop.

Select an option

Save BananaAcid/331cc3c073564f2cb5a831e04aef35e5 to your computer and use it in GitHub Desktop.
Powershell -- ask PollinationsAI for a Text

Ask PollinationsAI for a Text

... in pure Powershell 5+ / 7+ (Win, Linux, OSX, Docker, ...) -- for free (registration, but no moneys)

https://enter.pollinations.ai/

Warning

PollinationsAI will cache the response to your request indefinitely (possibly the request as well) and the response can be accessed without authentication.

This might be what you are looking for, if you want to get persistent results to a request or want to share the response (the URL visible with -Debug is without authentication).

DO NOT enter private data (name, address, ...), personal information, information about other people, financial data and other sensetive information. It is not save to use in a corporate environment. Handle it as if you would post on X / Facebook.

See Discussion

Usage

PollinationsAI-Text "a cat"
# Ah, a cat – these furry little bundles ...
PollinationsAI-Text -?
PollinationsAI-Text [-content] <string> [-settings <hashtable>] [-model <string>] [-POLLINATIONSAI_API_KEY <string>] [-bypassCache]
PollinationsAI-Text [-content] <string> -details [-settings <hashtable>] [-model <string>] [-POLLINATIONSAI_API_KEY <string>] [-bypassCache]
PollinationsAI-Text [-content] <string> -save [-details] [-settings <hashtable>] [-model <string>] [-POLLINATIONSAI_API_KEY <string>] [-bypassCache]
PollinationsAI-Text [-content] <string> -out <string> [-details] [-settings <hashtable>] [-model <string>] [-POLLINATIONSAI_API_KEY <string>] [-bypassCache]
PollinationsAI-Text -listModels [-details]
PollinationsAI-Text -getSettingsDefault

Yes: Optional <CommonParameters> is always supported.

Quickly integrate it (install, update)

Note

➡️ Interchangeably use PollinationsAI-Text for .\ask.pollinations_text.ps1 in this documentation. Exact same params apply.

PollinationsAI-Text can be used globally, using the file itself works only where it is saved.

In your Powershell prompt, paste the following to download the comandlet into the Powershell profile folder and activate it:

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/BananaAcid/331cc3c073564f2cb5a831e04aef35e5/raw/integrate.ps1'))

Note: Non-Windows users will see, which has no effect: Set-ExecutionPolicy: Operation is not supported on this platform.

only download it into your current folder
$ErrorActionPreference = 'SilentlyContinue'; Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-WebRequest 'https://gist.githubusercontent.com/BananaAcid/331cc3c073564f2cb5a831e04aef35e5/raw/ask.pollinations_text.ps1' -out 'ask.pollinations_text.ps1';

You might want to add your key as environment variable to your profile

"`n`n`$env:POLLINATIONSAI_API_KEY = `"sk_..............`"" >> $PROFILE.CurrentUserAllHosts

... after restarting your powershell console, the key will be available.

Params

arg default example desc
<string>
or -content <string>
or -prompt <string>
(required) "Some Text-Prompt" The content to be created.
-model <string> "nova-fast" "gemini" The model to use. Currently available on PollinationsAI.
-POLLINATIONSAI_API_KEY <string>
or -key <string>
$env:POLLINATIONSAI_API_KEY sk_12345678901234567890 Use a PollonationsAI API Key - if left set to "", $env:POLLINATIONSAI_API_KEY is being checked. Note: Add the API key to your environment variables.
-settings <hashtable>
or -set <hashtable>
see below @{seed = 1234567890} A hashtable of settings passed to the Pollinations AI API.
-bypassCache
or -nocache
Only bypasses the cloudflare cache, resulting in a newly generated response. Without, the first request will generate the result, each subsequent request will result in the cached response.
-out <string> answer.txt The local path to save the generated text and returns the path.
-save Will save to the system temp folder and returns the path.
-details Does not save but and returns @{ Headers; Content; Uri; [FilePath] } (FilePath only if -save or -out was used)
-getSettingsDefault
or -get
Get the default settings for the PollinationsAI API.
-listModels
or -list
Outputs a table of models, that are currently available on PollinationsAI.
-listModels -details
or -list -details
Outputs a Hashtable of models, to be used in code.
-debug Outputs the request URI. (This URI does not need authorisation, because it accesses the cached result)

Important

Returns:

  • Default: The generated text
  • -details: The headers as and content @{ Headers; Content; Uri; [FilePath] } (FilePath only if -save or -out was used)
    • (HTTP-response Headers, Content of the answer, Uri of the cached request)
  • -save: The local path to generated file
  • -out <name.txt>: The local path to generated file

🎵 Audio: You might get an audio file (using openai-audio), using -save will create a mpeg (mpga) file, returing it by default will be the bytes, as will be the -details content.

⚠️ Because the comandlet returns the paths or data, you can use it within another script!

Caution

on error:

  • throws
    @{ StatusCode = <error code>; Message = <error message> }

Note

You can always shorten a param (to use -c or -con instead of -content)

Make it available to your shell as a function (if you did not do the "quickly integrate it") ... for local use

Function PollinationsAI-Text { & <absolutepath>\ask.pollinations_text.ps1 @args }

Doing this, you can use PollinationsAI-Text -listModels in any folder (while in the same session), instead of .\ask.pollinations_text.ps1 -listModels within the script folder only.

To make it always available in a powershell session, add it a file shown with $Profile | Select-Object * (CurrentUserAllHosts is a good place).

Examples

Generate a text based on the prompt "a cat"

PollinationsAI-Text "a cat"
# Ah, a cat – these furry little bundles ...

Get all models and test a prompt

See discussion pollinations/pollinations#7423

# Nabil Redmann - 2026-01-24
# License: MIT
# https://gist.github.com/BananaAcid/331cc3c073564f2cb5a831e04aef35e5
[CmdletBinding(DefaultParameterSetName="None")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '', Scope = 'Function', Target = '*')]
<#
.SYNOPSIS
Generate text using the Pollinations AI API.
.DESCRIPTION
Generate text based on the given prompt using the Pollinations AI API.
.PARAMETER content
The prompt for the text.
.PARAMETER prompt
Alternative to content.
The prompt for the text.
.PARAMETER settings
A hashtable of settings passed to the Pollinations AI API.
.PARAMETER model
The model to use for text generation.
.PARAMETER POLLINATIONSAI_API_KEY
The API key to use for the Pollinations AI API.
.PARAMETER key
Alternative to POLLINATIONSAI_API_KEY.
The API key to use for the Pollinations AI API.
.PARAMETER out
The local path to save the generated text.
.PARAMETER save
Will save to the system temp folder.
.PARAMETER details
Will return the details of the generated text (headers + content).
.PARAMETER getSettingsDefault
Get the default settings for the Pollinations AI API.
.PaRAMETER listModels
Get the list of available models for the Pollinations AI API.
.EXAMPLE
PS C:\> .\ask.pollinations_text.ps1 -listModels
PS C:\> .\ask.pollinations_text.ps1 -content "a cat" -model "openai" -save
List the available models, then generate an text based on the prompt "a cat" and save it.
.EXAMPLE
PS C:\> .\ask.pollinations_text.ps1 "a cat" -set @{"system" = "just output a comma separated list of typical colors"}
Generate an text based on the prompt "a cat" and set the system prompt to "just output a comma separated list of typical colors".
.EXAMPLE
PS C:\> $env:POLLINATIONSAI_API_KEY = "sk_..."
PS C:\> $s = .\ask.pollinations_text.ps1 -getSettingsDefault
PS C:\> $s
Name Value
---- -----
system
temperature 1
seed 0
PS C:\> $s.temperature = 2.0
PS C:\> .\ask.pollinations_text.ps1 -content "a cat" -settings $s -out acat.jpg
.NOTES
Use -Debug to see the Write-Debug output
TEST with httpie:
https GET gen.pollinations.ai/text/describe%20a%20cat --verbose -A bearer -a sk_* model==nomnom
.OUTPUTS
The generated text content
OR
content and headers as @{ Headers; Content; Uri } using: -details
Error:
throws @{ StatusCode = <error code>; Message = <error message> }
#>
param (
[string]
[Parameter(Mandatory=$true, ParameterSetName='None', Position=0, HelpMessage="Prompt for the text")]
[Parameter(Mandatory=$true, ParameterSetName='WithOut', Position=0, HelpMessage="Prompt for the text")]
[Parameter(Mandatory=$true, ParameterSetName='WithSave', Position=0, HelpMessage="Prompt for the text")]
[Parameter(Mandatory=$true, ParameterSetName='WithDetails', Position=0, HelpMessage="Prompt for the text")]
[Alias("prompt")]
$content,
[hashtable]
[Parameter(Mandatory=$false, ParameterSetName='None', HelpMessage="A hashtable of settings passed to the Pollinations AI API, see https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}")]
[Parameter(Mandatory=$false, ParameterSetName='WithOut', HelpMessage="A hashtable of settings passed to the Pollinations AI API, see https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}")]
[Parameter(Mandatory=$false, ParameterSetName='WithSave', HelpMessage="A hashtable of settings passed to the Pollinations AI API, see https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}")]
[Parameter(Mandatory=$false, ParameterSetName='WithDetails', HelpMessage="A hashtable of settings passed to the Pollinations AI API, see https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}")]
$settings = @{},
[string]
[Parameter(Mandatory=$false, ParameterSetName='None', HelpMessage="The model to use for text generation. Defaults to 'ztext'. See https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}.query.model")]
[Parameter(Mandatory=$false, ParameterSetName='WithOut', HelpMessage="The model to use for text generation. Defaults to 'ztext'. See https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}.query.model")]
[Parameter(Mandatory=$false, ParameterSetName='WithSave', HelpMessage="The model to use for text generation. Defaults to 'ztext'. See https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}.query.model")]
[Parameter(Mandatory=$false, ParameterSetName='WithDetails', HelpMessage="The model to use for text generation. Defaults to 'ztext'. See https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}.query.model")]
$model = "nova-fast",
[string]
[Parameter(Mandatory=$false, ParameterSetName='None')]
[Parameter(Mandatory=$false, ParameterSetName='WithOut')]
[Parameter(Mandatory=$false, ParameterSetName='WithSave')]
[Parameter(Mandatory=$false, ParameterSetName='WithDetails')]
[Alias("key")]
$POLLINATIONSAI_API_KEY = $env:POLLINATIONSAI_API_KEY,
[switch]
[Parameter(Mandatory=$false, ParameterSetName='None')]
[Parameter(Mandatory=$false, ParameterSetName='WithOut')]
[Parameter(Mandatory=$false, ParameterSetName='WithSave')]
[Parameter(Mandatory=$false, ParameterSetName='WithDetails')]
[Alias("nocache")]
$bypassCache = $false, # this only bypasses the cloudflare cache, resulting in a newly generated response.
[string]
[Parameter(Mandatory=$true, ParameterSetName='WithOut')]
$out = "",
[switch]
[Parameter(Mandatory=$true, ParameterSetName='WithSave')]
$save = $false, # save a file with `-out <name>` or `-save` to save it with a provided name to the sys temp
[switch]
[Parameter(Mandatory=$true, ParameterSetName='WithDetails')]
[Parameter(Mandatory=$false, ParameterSetName='WithOut')]
[Parameter(Mandatory=$false, ParameterSetName='WithSave')]
[Parameter(Mandatory=$false, ParameterSetName='GetModelsList')]
$details = $false,
# stand alone
[switch]
[Parameter(Mandatory=$true, ParameterSetName='GetSettingsDefault')]
$getSettingsDefault = $false,
# stand alone
[switch]
[Parameter(Mandatory=$true, ParameterSetName='GetModelsList')]
$listModels = $false
)
# ---------------------------------------------------------------
<#
.LINK
https://enter.pollinations.ai/api/docs#tag/genpollinationsai/GET/text/{prompt}
#>
$defaultSettingsByApi = @{
seed = 0 # 0 == random, max == 9007199254740991
system = ""
temperature = 1.0
voice = "alloy" # only for openai-audio, see https://platform.openai.com/docs/guides/text-to-speech#voice-options
}
if ($getSettingsDefault) {
return $defaultSettingsByApi
}
if ($listModels -eq $true) {
$response = Invoke-WebRequest -Uri "https://gen.pollinations.ai/text/models" -Method Get -UseBasicParsing
$list = $response.content | ConvertFrom-Json |? {$_.output_modalities -Contains "text"}
if ($details) {
return $list
}
else {
return $list | Format-Table
}
}
# ---------------------------------------------------------------
if (-not $POLLINATIONSAI_API_KEY) { throw "⚠️ POLLINATIONSAI API KEY is missing! (-key or -POLLINATIONSAI_API_KEY or set `$env:POLLINATIONSAI_API_KEY=`"sk_...`")" }
# ---------------------------------------------------------------
#* we do not merge the defaults into this settings object by default, because the generated URL query would be longer then necessary
$querySettings = @{
"model" = if (-not $model) { "nova-fast" } else { $model } # since this could be set to ""
#"json" = "true" # we always want the response as JSON #! *JSON-BUG ... But that results in plaintext or json formatted error https://github.com/pollinations/pollinations/issues/7413
} + $settings
# bypasses cloudflare cache
if ($bypassCache) {
$querySettings["cacheBuster"] = [string](Get-Date).Ticks + (Get-Random)
}
$headers = @{
"Authorization" = "Bearer $POLLINATIONSAI_API_KEY"
}
$baseUrl = "https://gen.pollinations.ai/text"
# stringify query and convert prompt
$queryStr = ($querySettings.GetEnumerator() |% { [uri]::EscapeDataString($_.Key) + "=" + [uri]::EscapeDataString($_.Value) } ) -join "&"
$promptSlug = [uri]::EscapeDataString($content)
# construct URI
$uri = "{0}/{1}?{2}" -f $baseUrl, $promptSlug, $queryStr
Write-Debug "URI: $uri"
# check for PowerShell 7+
$canSkip = (Get-Command Invoke-WebRequest).Parameters.ContainsKey('SkipHttpErrorCheck')
if ($canSkip) {
$response = Invoke-WebRequest -Uri $uri -Method Get -Headers $headers -UseBasicParsing -SkipHttpErrorCheck # get the error message in the response
}
else {
# Fallback for PowerShell 5.1 --> does only show the status code, since the response is dropped by Invoke-WebRequest
try {
$response = Invoke-WebRequest -Uri $uri -Method Get -Headers $headers -UseBasicParsing -ErrorAction Stop
}
catch {
$response = @{ StatusCode = $_.Exception.Response.StatusCode.Value__; Message = $_.Exception.Response.StatusCode }
}
}
# check for errors
if ($response.StatusCode -ne 200) {
$err = if ($response.content) {$response.content | ConvertFrom-Json |% { @{ StatusCode = $_.status; Message = $_.error.message} }} else { $response }
Write-Error $err
# set error code
$global:LASTEXITCODE = $response.StatusCode
throw [PSCustomObject]$err
}
#! *JSON-BUG ... The json param does not work. It results in plaintext or json formatted error https://github.com/pollinations/pollinations/issues/7413
# elseif ($response.Headers["Content-Type"] -notlike "*/json") {
# Write-Error $response.Content
# # set error code
# $global:LASTEXITCODE = 200
# throw [PSCustomObject]@{ StatusCode = $response.StatusCode; Message = $response.Content }
# }
$ret = ""
# save the text
if ($out -ne "" -or $save -eq $true) {
if ($out -eq "") {
#* NOTE: 'Content-Disposition' is always missing on the text endpoint
$targetFilename = $response.Headers["X-Request-ID"].Trim()
if ($targetFilename -eq "") { $targetFilename = (Get-Date).ToString("yyyyMMddHHmmss") + "-" + (Get-Random) }
# dir is temp dir
$targetDir = [IO.Path]::GetTempPath()
$filepath = [IO.Path]::Combine($targetDir, $targetFilename)
}
else {
$filepath = [IO.Path]::Combine($PWD, $out)
}
if ($Null -eq (Split-Path $filepath -Leaf).Split(".")[1]) { #PWSH 6+ "" -eq (Split-Path $filepath -Leaf | Split-Path -Extension)
# 'text/html' ... 'application/json' ...
$type = $response.Headers["Content-Type"] -split ";" | select -First 1 |% { $_ -split "/"} | Select-Object -Last 1
if ($type -eq "" -or $type -eq "plain") { $type = "txt" }
$filepath += "." + $type
}
Write-Debug "Filepath: $filepath"
if ($response.Content.GetType().Name -eq "Byte[]") {
# save bytes (possibly audio)
[IO.File]::WriteAllBytes($filepath, $response.Content)
}
else {
# save the text
$response.Content | Out-File -FilePath $filepath
}
$ret = $filepath
}
if ($details -eq $true) {
$ret = if ($ret) { @{ FilePath = $ret } } else { @{} } #filename available
$ret = $ret + @{
Headers = $response.Headers
Content = $response.Content
Uri = $uri
}
}
if ($ret) {
return $ret
}
else {
return $response.Content
}
<#
!== 200
Content-Type: application/json
{
"error": {
"code": "...",
"message": "...",
"timestamp": "0000-00-00T00:00:00.123Z"
},
"status": ...,
"success": false
}
? 200 - positive result, uncached
NOTE:
header has Content-Type: text/plain
body is utf-8
HEADERS:
Key Value
--- -----
Date {Sun, 18 Jan 2026 10:14:56 GMT}
Transfer-Encoding {chunked}
Connection {keep-alive}
CF-Ray {9bfd54021e6ed949-AMS}
CF-Cache-Status {DYNAMIC}
Access-Control-Allow-Origin {*}
Cache-Control {public, max-age=31536000, immutable}
ETag {W/"298-MnNrRl5T1531wa7aJ/spgQsXBQ0"}
Server {cloudflare}
X-Cache-Key {ce5a237ffd2669f5}
X-Content-Type-Options {nosniff}
X-Powered-By {Express}
Access-Control-Expose-Headers {Content-Length,Content-Disposition}
X-Cache {MISS}
x-model-used {amazon.nova-micro-v1:0}
X-Request-ID {4e1b7f56-f9ba-4819-a904-fccd80c77405}
x-usage-completion-text-tokens {154}
x-usage-prompt-text-tokens {256}
x-usage-total-tokens {410}
Strict-Transport-Security {max-age=0; includeSubDomains; preload}
Speculation-Rules {"/cdn-cgi/speculation"}
Vary {accept-encoding}
Server-Timing {cfCacheStatus;desc="DYNAMIC", cfEdge;dur=1383,cfOrigin;dur=0}
Alt-Svc {h3=":443"}
Content-Type {text/plain; charset=utf-8}
HEADERS - Audio specific:
x-model-used {gpt-4o-mini-audio-preview-2024-12-17}
Content-Type {audio/mpeg}
- Request params by Pollinations:
{"messages":[{"role":"user","content":"a cat"}],"jsonMode":false,"model":"openai-audio","referrer":null,"isPrivate":false,"voice":"alloy","modalities":["text","audio"],"audio":{"voice":"alloy","format":"mp3"}}
#>
<#
Download and integrate into Powershell Profile
#>
$p = $PROFILE.CurrentUserAllHosts
$path = $p | Split-Path -Parent
# create profile.ps1 if it is missing (linux, ...)
if (-not (Test-Path -Path $p -PathType Leaf)) {
New-Item -Path $p -ItemType File -Force | Out-Null
}
# download newset version of ask.pollinations_text.ps1
Invoke-WebRequest "https://gist.githubusercontent.com/BananaAcid/331cc3c073564f2cb5a831e04aef35e5/raw/ask.pollinations_text.ps1" -OutFile "$path\ask.pollinations_text.ps1"
# add function to profile
$integrate = "`n`n# ask.pollinations_text.ps1`nFunction PollinationsAI-Text { `$p = `$PSScriptRoot; if (`$args -contains `"-?`") { `$x = & `$p\ask.pollinations_text.ps1 -?; `$x -replace `"ask.pollinations_text.ps1`", `"PollinationsAI-Text`"} else { & `$p\ask.pollinations_text.ps1 @args } }"
if ( $null -eq (Select-String -Path $p -Pattern "ask.pollinations_text.ps1") ) {
$integrate | Out-File -FilePath $p -Append
}
# active in current session
Remove-Item Function:PollinationsAI-Text -ErrorAction SilentlyContinue
Invoke-Expression $integrate.replace("`$PSScriptRoot", "`"$path`"")
Write-Output "🟢 Done, PollinationsAI-Text is now available.`n`n 💡 Run 'PollinationsAI-Text -List' to see available models.`n ⭐ Set `$env:POLLINATIONSAI_API_KEY to your API key, or use the -key param.`n 📄 Have a look at the documentation: https://gist.github.com/BananaAcid/6bc2fc33d948d28d255674a7613f120c`n`n ➡️ Try it out: PollinationsAI-Text `"a cat`""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment