Is RoPro - Enhance Your Roblox Experience safe?
RoPro is medium risk. Submitting a Roblox trade offer makes RoPro POST to api.ropro.io/postWishlist.php with your Roblox ID and up to four wanted/offered item IDs. Analysis couldn't finish the post since Roblox needed Premium; the script/mapping are present.
Who publishes itRoPro Software Corporation - no other listings under this identity, 1 shared hostname
RoPro Software Corporation - no other listings under this identity, 1 shared hostname
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 1 hostname
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Trade offer posts send wishlist item IDs to RoPro
Submitting a Roblox trade offer makes RoPro POST to api.ropro.io/postWishlist.php with your Roblox ID and up to four wanted/offered item IDs.
Analysis couldn't finish the post since Roblox needed Premium; the script/mapping are present.
You submit a Roblox trade-board offer with selected wanted and offered items.
RoPro prepares a request to its API containing your Roblox user ID and the selected item IDs.
| Field | Value | Why it matters | |
|---|---|---|---|
Your Roblox user ID | userid=12345678 (illustrative) | Connects the posted trade-board offer to your Roblox account. | |
Wanted item slots | want_item=1365767&want_item2=144630&want_item3=-1&want_item4=-1 (illustrative) | Shows which Roblox items or trade terms you selected as items you want. | |
Offered item slots | item1=1029025&item2=17954048&item3=-1&item4=-1 (illustrative) | Shows which Roblox items you selected as items you are offering. | |
Offer note and value | want_value=0¬e= | Adds trade-board context alongside the selected items. |
| ropro-id | Roblox user ID from the authenticated extension state |
The content script builds the trade-offer payload, and the background script maps it to RoPro's API.
function postWishlist(payload) {
return new Promise((resolve) => {
roproApiAdapter.request("ropro_post_wishlist", payload, function (data) {
resolve(data);
});
});
}async function submitComposerOffer() {
if (getComposerOfferedSelectedCount() === 0) {
updateComposerStatus("Select at least one offered item.");
return;
}
if (offersState.composer.wantedSelected.length === 0) {
updateComposerStatus("Select at least one wanted item.");
return;
}
var submitButton = offersState.composer.overlay
? offersState.composer.overlay.querySelector(".ropro-trade-offers-submit")
: null;
if (submitButton != null) {
submitButton.disabled = true;
}
updateComposerStatus("Posting offer...");
var offered = [];
for (var offeredIndex = 0; offeredIndex < offersState.composer.offeredSelected.length; offeredIndex++) {
var offeredEntry = offersState.composer.offeredSelected[offeredIndex];
var quantity = parseInt(offeredEntry.quantity, 10);
if (!Number.isFinite(quantity) || quantity <= 0) {
quantity = 1;
}
for (var quantityIndex = 0; quantityIndex < quantity && offered.length < 4; quantityIndex++) {
offered.push(offeredEntry);
}
if (offered.length >= 4) {
break;
}
}
var wanted = offersState.composer.wantedSelected.slice(0, 4);
function getPostedItemId(entry, side) {
if (entry == null || typeof entry !== "object") {
return -1;
}
if (entry.isTerm === true) {
return Number.isFinite(parseInt(entry.id, 10)) ? parseInt(entry.id, 10) : -1;
}
if (side === "offered") {
return Number.isFinite(parseInt(entry.assetId, 10)) ? parseInt(entry.assetId, 10) : -1;
}
return Number.isFinite(parseInt(entry.id, 10)) ? parseInt(entry.id, 10) : -1;
}
var payload = {
userId: offersState.myUserId,
want_item: getPostedItemId(wanted[0], "wanted"),
want_item2: getPostedItemId(wanted[1], "wanted"),
want_item3: getPostedItemId(wanted[2], "wanted"),
want_item4: getPostedItemId(wanted[3], "wanted"),
want_value: 0,
item1: getPostedItemId(offered[0], "offered"),
item2: getPostedItemId(offered[1], "offered"),
item3: getPostedItemId(offered[2], "offered"),
item4: getPostedItemId(offered[3], "offered"),
note: "",
};
var parsed = null;
try {
var response = await postWishlist(payload);
parsed = parsePayload(response);
} catch (_) {
parsed = null;
}
if (submitButton != null) {
submitButton.disabled = false;
}
if (parsed == null || parsed === "ERROR") {
updateComposerStatus("Unable to post offer right now. Please try again.");
return;
}
if (typeof parsed !== "object") {
updateComposerStatus("Unable to confirm the post response. Please try again.");
return;
}
if (typeof parsed.error === "string" && parsed.error.length > 0) {
syncTradeOfferPostCooldownFromPayload(parsed);
updateComposerStatus(parsed.error);
return;
}
var postedWishId = parseInt(parsed.wishid, 10);
if (parsed.success !== true && !Number.isFinite(postedWishId)) {
syncTradeOfferPostCooldownFromPayload(parsed);
updateComposerStatus("Unable to confirm that your offer posted. Please refresh and try again.");
return;
}
syncTradeOfferPostCooldownFromPayload(parsed);
if (getTradeOfferPostCooldownRemainingSeconds() <= 0) {
setTradeOfferPostCooldown(
offersState.postCooldown.cooldownSeconds,
offersState.postCooldown.cooldownSeconds
);
}
updateComposerStatus("Offer posted.");
closeComposerModal();
await loadTradeOffers(true);
}ropro_post_wishlist: {
path: "postWishlist.php",
method: "POST",
capability: "trade_offers_post",
buildRequest: function (payload) {
var rawUserId = payload.userId ?? payload.userid;
var userId = null;
if (rawUserId != null && String(rawUserId).trim().length > 0) {
userId = normalizeRoProInteger(rawUserId, {
min: 1,
});
if (userId == null) {
return null;
}
}
var wantItem = normalizeRoProInteger(payload.want_item, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var wantItem2 = normalizeRoProInteger(payload.want_item2, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var wantItem3 = normalizeRoProInteger(payload.want_item3, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var wantItem4 = normalizeRoProInteger(payload.want_item4, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var wantValue = normalizeRoProInteger(payload.want_value, {
min: -10000000,
max: 10000000,
});
var item1 = normalizeRoProInteger(payload.item1, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var item2 = normalizeRoProInteger(payload.item2, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var item3 = normalizeRoProInteger(payload.item3, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var item4 = normalizeRoProInteger(payload.item4, {
min: -9,
max: Number.MAX_SAFE_INTEGER,
});
var note = normalizeRoProString(payload.note, 40, { allowEmpty: true });
if (
wantItem == null ||
wantItem2 == null ||
wantItem3 == null ||
wantItem4 == null ||
wantValue == null ||
item1 == null ||
item2 == null ||
item3 == null ||
item4 == null ||
note == null
) {
return null;
}
var requestBody = {
want_item: wantItem,
want_item2: wantItem2,
want_item3: wantItem3,
want_item4: wantItem4,
want_value: wantValue,
item1: item1,
item2: item2,
item3: item3,
item4: item4,
note: note,
};
if (userId != null) {
requestBody.userid = userId;
}
return {
bodyType: "form",
body: requestBody,
};
},
}- api.ropro.io
Receives the trade-board wishlist POST addressed to /postWishlist.php.