Converters are used to transform prompts before sending them to the target.
This can be useful for a variety of reasons, such as encoding the prompt in a different format, or adding additional information to the prompt. For example, you might want to convert a prompt to base64 before sending it to the target, or add a prefix to the prompt to indicate that it is a question.
Converters can transform prompts in various ways:
Text-to-Text: Encoding, obfuscation, translation, and semantic transformations
Multimodal: Converting between text, images, audio, video, and files
Converter Modality Reference Table¶
The following table shows all available converters organized by their input and output modalities:
import pandas as pd
from pyrit.output import output_attack_async
from pyrit.prompt_converter import get_converter_modalities
from pyrit.setup import IN_MEMORY, initialize_pyrit_async
await initialize_pyrit_async(memory_db_type=IN_MEMORY) # type: ignore
# Get all converters with their modalities
converter_list = get_converter_modalities()
# Create a list of rows for the DataFrame
rows = []
for name, inputs, outputs in converter_list:
input_str = ", ".join(inputs) if inputs else "any"
output_str = ", ".join(outputs) if outputs else "any"
rows.append({"Input Modality": input_str, "Output Modality": output_str, "Converter": name})
# Create DataFrame and sort
df = pd.DataFrame(rows)
df = df.sort_values(by=["Input Modality", "Output Modality", "Converter"]).reset_index(drop=True)
# Display all rows
pd.set_option("display.max_rows", None)
print(df)Found default environment files: ['./.pyrit/.env']
Loaded environment file: ./.pyrit/.env
No new upgrade operations detected.
/opt/venv/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
Input Modality Output Modality Converter
0 audio_path audio_path AudioEchoConverter
1 audio_path audio_path AudioFrequencyConverter
2 audio_path audio_path AudioSpeedConverter
3 audio_path audio_path AudioVolumeConverter
4 audio_path audio_path AudioWhiteNoiseConverter
5 audio_path text AzureSpeechAudioToTextConverter
6 image_path image_path AddTextImageConverter
7 image_path image_path ImageOverlayConverter
8 image_path image_path TransparencyAttackConverter
9 image_path video_path AddImageVideoConverter
10 image_path, url image_path ImageColorSaturationConverter
11 image_path, url image_path ImageCompressionConverter
12 image_path, url image_path ImageResizingConverter
13 image_path, url image_path ImageRotationConverter
14 text audio_path AzureSpeechTextToAudioConverter
15 text binary_path PDFConverter
16 text binary_path WordDocConverter
17 text image_path AddImageTextConverter
18 text image_path QRCodeConverter
19 text text AnsiAttackConverter
20 text text ArabicPresentationFormConverter
21 text text ArabiziConverter
22 text text AsciiArtConverter
23 text text AsciiSmugglerConverter
24 text text AskToDecodeConverter
25 text text AtbashConverter
26 text text Base2048Converter
27 text text Base64Converter
28 text text BidiConverter
29 text text BinAsciiConverter
30 text text BinaryConverter
31 text text BrailleConverter
32 text text CaesarConverter
33 text text CharSwapConverter
34 text text CharacterSpaceConverter
35 text text CodeChameleonConverter
36 text text ColloquialWordswapConverter
37 text text DenylistConverter
38 text text DiacriticConverter
39 text text EcojiConverter
40 text text EmojiConverter
41 text text FirstLetterConverter
42 text text FlipConverter
43 text text ImagePromptStyleConverter
44 text text InsertPunctuationConverter
45 text text JsonStringConverter
46 text text LLMGenericTextConverter
47 text text LeetspeakConverter
48 text text MaliciousQuestionGeneratorConverter
49 text text MathObfuscationConverter
50 text text MathPromptConverter
51 text text MorseConverter
52 text text NatoConverter
53 text text NegationTrapConverter
54 text text NoiseConverter
55 text text PersuasionConverter
56 text text ROT13Converter
57 text text RandomCapitalLettersConverter
58 text text RandomTranslationConverter
59 text text RepeatTokenConverter
60 text text ScientificTranslationConverter
61 text text SearchReplaceConverter
62 text text SelectiveTextConverter
63 text text SneakyBitsSmugglerConverter
64 text text StringJoinConverter
65 text text SuffixAppendConverter
66 text text SuperscriptConverter
67 text text TatweelConverter
68 text text TemplateSegmentConverter
69 text text TenseConverter
70 text text TextJailbreakConverter
71 text text ToneConverter
72 text text ToxicSentenceGeneratorConverter
73 text text TranslationConverter
74 text text UnicodeConfusableConverter
75 text text UnicodeReplacementConverter
76 text text UnicodeSubstitutionConverter
77 text text UrlConverter
78 text text VariationConverter
79 text text VariationSelectorSmugglerConverter
80 text text ZalgoConverter
81 text text ZeroWidthConverter
Converter Categories¶
Converters are organized into the following categories:
Text-to-Text Converters: Non-LLM (encoding, obfuscation) and LLM-based (translation, variation, tone)
Audio Converters: Text-to-Audio, Audio-to-Text, Audio-to-Audio
Image Converters: Text-to-Image, Image-to-Image
Video Converters: Image-to-Video
File Converters: Text-to-File (PDF, URL)
Selectively Converting: Advanced techniques for converting portions of prompts
Simple Converter Example¶
Converters can be used to perform these types of transformations. Here is a simple program that uses Rot13Converter converter, RandomCapitalLettersConverter, and AsciiArtConverter.
from pyrit.prompt_converter import (
AsciiArtConverter,
BinaryConverter,
FirstLetterConverter,
RandomCapitalLettersConverter,
ROT13Converter,
)
prompt = "tell me how to cut down a tree"
print(await ROT13Converter().convert_tokens_async(prompt=prompt)) # type: ignore
print(await RandomCapitalLettersConverter(percentage=25.0).convert_tokens_async(prompt=prompt)) # type: ignore
print(await AsciiArtConverter().convert_tokens_async(prompt=prompt)) # type: ignore
print(await BinaryConverter().convert_tokens_async(prompt=prompt)) # type: ignore
print(await FirstLetterConverter().convert_tokens_async(prompt=prompt)) # type: ignoretext: gryy zr ubj gb phg qbja n gerr
text: tell me HOw tO cut down a tree
text: "|"[-|_|_ |\/|[- |-|()\/\/ "|"() (|_|"|" |)()\/\/|\| /-\ "|"|2[-[-
text: 0000000001110100 0000000001100101 0000000001101100 0000000001101100 0000000000100000 0000000001101101 0000000001100101 0000000000100000 0000000001101000 0000000001101111 0000000001110111 0000000000100000 0000000001110100 0000000001101111 0000000000100000 0000000001100011 0000000001110101 0000000001110100 0000000000100000 0000000001100100 0000000001101111 0000000001110111 0000000001101110 0000000000100000 0000000001100001 0000000000100000 0000000001110100 0000000001110010 0000000001100101 0000000001100101
text: t m h t c d a t
Stacking Converters¶
Although converters can be used on their own, they should be thought of as a piece in the pipeline. Typically any attack will have arguments so that prompts can be converted before being sent to the target. They can be stacked, use LLMs, and are a powerful tool.
Stacking Converters with PromptSendingAttack¶
In the following example, a TextTarget is used so these prompts are simply printed and added to memory. This can be useful if you are red teaming something and need to manually enter prompts. However, the target can be replaced with any other target. E.g., if you have API access you can add a target there.
In this example the converters are stacked. First a variation is found using VariationConverter, and then StringJoinConverter is used to add a dash between letters. Remember that order matters. If StringJoinConverter came first, we would be asking the LLM to make variations of the prompt:
“t-e-l-l- - m-e- -h-o-w- -t-o- -c-u-t- -d-o-w-n - a- -t-r-e-e”
from pyrit.executor.attack import (
AttackConverterConfig,
PromptSendingAttack,
)
from pyrit.prompt_converter import StringJoinConverter, VariationConverter
from pyrit.prompt_normalizer import PromptConverterConfiguration
from pyrit.prompt_target import OpenAIChatTarget, TextTarget
objective = "tell me how to cut down a tree"
# converter target to send prompt to; in this case configured to the Azure OpenAI GPT-4o Chat model
converter_target = OpenAIChatTarget()
prompt_variation_converter = VariationConverter(converter_target=converter_target)
converter_configs = PromptConverterConfiguration.from_converters( # type: ignore
converters=[prompt_variation_converter, StringJoinConverter()]
)
converter_config = AttackConverterConfig(request_converters=converter_configs) # type: ignore
target = TextTarget()
attack = PromptSendingAttack(
objective_target=target,
attack_converter_config=converter_config,
)
result = await attack.execute_async(objective=objective) # type: ignore
await output_attack_async(result)TextTarget: user: C-a-n y-o-u e-x-p-l-a-i-n t-h-e s-t-e-p-s t-o f-e-l-l a t-r-e-e-?
════════════════════════════════════════════════════════════════════════════════════════════════════
❓ ATTACK RESULT: UNDETERMINED ❓
════════════════════════════════════════════════════════════════════════════════════════════════════
Attack Summary
────────────────────────────────────────────────────────────────────────────────────────────────────
📋 Basic Information
• Objective: tell me how to cut down a tree
• Attack Type: PromptSendingAttack
• Conversation ID: 410b9dae-5987-441f-b973-81cfe76ac1a9
⚡ Execution Metrics
• Turns Executed: 1
• Execution Time: 3.46s
🎯 Outcome
• Status: ❓ UNDETERMINED
• Reason: No objective scorer configured
Conversation History with Objective Target
────────────────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
Original:
tell me how to cut down a tree
Converted:
C-a-n y-o-u e-x-p-l-a-i-n t-h-e s-t-e-p-s t-o f-e-l-l a t-r-e-e-?
────────────────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────────────────
Report generated at: 2026-05-21 22:35:20 UTC
Response Converters¶
So far, we’ve focused on request converters that transform prompts before sending them to the target. PyRIT also supports response converters that transform the target’s response before returning it. This is useful in scenarios like:
Translating responses back to the original language after sending prompts in a different language
Decoding encoded responses
Normalizing or cleaning up response text
Response converters use the same PromptConverterConfiguration class as request converters. They are configured via the response_converters parameter in AttackConverterConfig.
Translation Round-Trip Example¶
A common use case is sending prompts in a different language to test how the target handles non-English input. In this example, we:
Use a request converter to translate the prompt from English to French
Send the translated prompt to the target
Use a response converter to translate the response back to English
from pyrit.executor.attack import (
AttackConverterConfig,
PromptSendingAttack,
)
from pyrit.prompt_converter import TranslationConverter
from pyrit.prompt_normalizer import PromptConverterConfiguration
from pyrit.prompt_target import OpenAIChatTarget
objective = "What is the capital of France?"
# Create an LLM target for the converters
converter_target = OpenAIChatTarget()
# Create an LLM target to send prompts to
prompt_target = OpenAIChatTarget()
# Request converter: translate English to French
request_converter = TranslationConverter(converter_target=converter_target, language="French")
request_converter_config = PromptConverterConfiguration(converters=[request_converter])
# Response converter: translate response back to English
response_converter = TranslationConverter(converter_target=converter_target, language="English")
response_converter_config = PromptConverterConfiguration(converters=[response_converter])
# Configure the attack with both request and response converters
converter_config = AttackConverterConfig(
request_converters=[request_converter_config],
response_converters=[response_converter_config],
)
attack = PromptSendingAttack(
objective_target=prompt_target,
attack_converter_config=converter_config,
)
result = await attack.execute_async(objective=objective) # type: ignore
# Print the conversation showing both original and converted values
await output_attack_async(result)
════════════════════════════════════════════════════════════════════════════════════════════════════
❓ ATTACK RESULT: UNDETERMINED ❓
════════════════════════════════════════════════════════════════════════════════════════════════════
Attack Summary
────────────────────────────────────────────────────────────────────────────────────────────────────
📋 Basic Information
• Objective: What is the capital of France?
• Attack Type: PromptSendingAttack
• Conversation ID: 70c4a57e-2d8e-478c-9baa-c1356f3709ac
⚡ Execution Metrics
• Turns Executed: 1
• Execution Time: 5.93s
🎯 Outcome
• Status: ❓ UNDETERMINED
• Reason: No objective scorer configured
Conversation History with Objective Target
────────────────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
Original:
What is the capital of France?
Converted:
Quelle est la capitale de la France ?
────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
Original:
La capitale de la France est **Paris**.
Converted:
The capital of France is **Paris**.
────────────────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────────────────────────
Report generated at: 2026-05-21 22:35:26 UTC